Java多线程编程技术方案原理
一 ,多线程相关的一些概念
1,线程和进程:
线程指的是进程中一个单一顺序的控制流,
进程中可以并发多个线程,每条线程并行执行不同的任务,被认为是一个计算资源的集合。进程不能被任务是一个应用,因为有些应用有多个进程组成。
2,并行与并发:
并发:单核cpu运行多线程时,在一个时间段内,多个线程交叉运行,给人感觉是同时运行。
并行:多核cpu运行 多线程时,真正的在同一时刻运行。
所以如果是单核多线程并发执行,并不需要处理多线程的同步问题。
3,线程同步和线程安全:
线程同步: 多个并行执行的线程在同一时刻不会执行指定的程序段。
线程安全:在多线程并行运行环境下而不会引发数据错误。线程安全问题都是由“全局变量及静态变量”引起的。若每个线程中对全局变量、静态变量只有读操作,而无写操作,一般来说,这个全局变量是线程安全的;若有多个线程同时执行写操作,一般都需要考虑线程同步,否则的话就可能影响线程安全。
区别:线程同步是解决线程安全的方法之一。
4,多线程的优点和缺点:
1,有写耗时的任务放在后台运行,不用等待。
2,一些等待的任务,比如用户输入,文件读取和网络收发数据,不用等待完成。
3,整体效率更高
缺点:线程切换消耗,线程的同步控制,更多的线程空间。
5,线程池技术:
线程池技术并不是实现线程同步,或者实现线程安全的技术。只是解决了大量线程的重建的消耗,池中保持一定数量的线程,即时开始处理任务。它是一种实现高并发的方案。比如说在Reactor多线程模型中使用了线程池技术。
6,JVM并发编程中的3个概念:
6.1,原子性
可认为时不可切分的操作,可以说一个指令,也可以有序的多个指令。要么完全执行成功,要么失败回退。
注意:一条Java语句,并不等同于一个原子性指令。
6.2,可见性
举例有三个线程并发,A , B , C线程, 访问同一个变量时,A线程修改了这个变量的值,B, C线程能够立即看得到修改的值。
6.3,有序性
程序执行的顺序按照代码的先后顺序执行。 JVM 内部对程序的有序性做了一些规范,能保证程序运行有序性。
但是存在指令重排的问题。一般来说,处理器为了提高程序运行效率,可能会对输入代码进行优化,最终会保证结果的一致性。
以上3个因素发生变化,都会影响到“线程同步”问题。以下同步解决方案中,都是为了解决这3个概念中的问题。
二,线程安全的技术方案
2.1 volatile变量技术:
作用于被操作的共享变量对象上。解决可见性问题。当一个共享变量被volatile修饰时,它会保证修改的值会立即被更新到主存,当有其他线程需要读取时,它会去内存中读取新值。而普通变量不能保证完全的可见性。
2.1.1作用:
1,保证了可见性
2,避免了JVM的指令重排序
缺点是volatile也无法保证对变量的任何操作都是原子性的。不能形成内存栅栏。
2.1.2 使用场景:
volatile关键字用于声明简单类型变量,如int、float、boolean等数据类型。如果这些简单数据类型声明为volatile,对它们的操作就会变成原子级别的。
原因是声明为volatile的简单变量,如果当前值由该变量以前的值相关,那么volatile关键字不起作用,也就是说如下的表达式都不是原子操作:
n = n + 1;
n++;
//作为标记状态量 volatile boolean flag = false; //线程1
while(!flag){ //默认情况执行
doSomething();
} //线程2
public void setFlag() { //线程2执行后,线程1停止
flag = true; //对于变量的操作时原子性的,不依赖于前值。
}
实现功能;实现了并发运行,以及对2个线程的切换。
1, 默认,线程1执行, 线程2未运行。
2,线程2运行, 线程1停止。
2.2 synchronized技术 (Java的线程同步技术之一)
在并发编程中,解决了原子性问题, 作用于多个线程的共同代码上。某个线程修改共享资源的时候,其他线程不能修改该资源,等待修改完毕同步之后,才能去抢夺CPU资源,完成对应的操作,保证了数据的同步性,解决了线程不安全的现象。
2.2.1 同步方法;
可理解为对“该方法所属的对象加锁” ,一次只能一个线程拿到锁,开始执行。也就是说,在同一个时间片内,并发执行的线程(同时执行到当前方法的线程)只有一个可以运行,其他线程必须等待。所以一般效率比较低。
2.2.2 同步代码块:
同步代码块锁定的代码范围更小,多个并发线程更大灵活性更大,毕竟代码块外部的指令依旧可以执行。而且锁定代码块也会更快执行完成。
2.3 CAS机制:属于乐观锁机制,适合并发冲突比较少的场合。
线程A 操作共享变量后,假定其他线程并没有操作该变量。则直接放回该变量。 如果内存的值不是预期值(也即是其他线程操作了该变量,虽然概率很低),则不做任何改变,返回 false。
2.3.1 机制说明:
1,操作变量后,和主内存对比, 失败后,一般开启继续重试。
2,重试的过程是,继续循环过程1,继续拉去新的共享变量,操作然后重新对比。 可理解为,总能找都一个时间片,没有存在并发冲突。
CAS 是 compare and swap 的简写,即比较并交换。它是指一种操作机制,而不是某个具体的类或方法。在 Java 平台上对这种操作进行了包装。在 Unsafe 类中,调用代码如下
unsafe.compareAndSwapInt(this, valueOffset, expect, update);
作为一种底层机制, CAS 在 Java 的原子类和并发包中有大量使用。
CAS 底层是靠调用 CPU 指令集的 cmpxchg 完成的。但是这种方案容易引发一个典型问题:ABA 问题 ,可以通过加版本号解决。
2.4 等待唤醒机制:或者称为“线程通信模型”
wait/notify 就是线程间的一种协作机制。
2.5 Atomic : 原子类
2. 6 Lock锁机制:
AQS是AbstractQueuedSynchronizer的缩写)
(后续补充, 还有补充代码实践演示。)
三, 其他一些相关概念:
悲观锁和乐观锁概念:
悲观锁:和独占锁是一个意思,它假设一定会发生冲突,因此获取到锁之后会阻塞其他等待线程。典型方案是synchronized方案
乐观锁:假设不会产生冲突,先去尝试执行某项操作,失败了再进行其他处理(一般都是不断循环重试),适用于同步冲突比较少的场合。典型方案是CAS方案
公平锁和非公平锁:
公平锁是指各个线程在加锁前先检查有无排队的线程,按排队顺序去获得锁。
非公平锁是指线程加锁前不考虑排队问题,直接尝试获取锁,获取不到再去队尾排队。
可重入锁和不可重入锁:
如果一个线程已经获取到了一个锁,那么它可以访问被这个锁锁住的所有代码块。不可重入锁与之相反。
死锁概念:两个线程相互等待的状态就形成了死锁。
Java多线程编程技术方案原理的更多相关文章
- Java多线程编程核心技术(三)多线程通信
线程是操作系统中独立的个体,但这些个体如果不经过特殊的处理就不能成为一个整体.线程间的通信就是成为整体的必用方案之一,可以说,使线程间进行通信后,系统之间的交互性会更强大,在大大提高CPU利用率的同时 ...
- Java多线程编程详解
转自:http://programming.iteye.com/blog/158568 线程的同步 由于同一进程的多个线程共享同一片存储空间,在带来方便的同时,也带来了访问冲突这个严重的问题.Ja ...
- Java多线程编程核心技术
Java多线程编程核心技术 这本书有利于对Java多线程API的理解,但不容易从中总结规律. JDK文档 1. Thread类 部分源码: public class Thread implements ...
- Java多线程编程实战指南(核心篇)读书笔记(四)
(尊重劳动成果,转载请注明出处:http://blog.csdn.net/qq_25827845/article/details/76690961冷血之心的博客) 博主准备恶补一番Java高并发编程相 ...
- Java多线程编程总结(精华)
Java多线程编程总结 2007-05-17 11:21:59 标签:多线程 java 原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http ...
- 《java多线程编程核心技术》(一)使用多线程
了解多线程 进程和多线程的概念和线程的优点: 提及多线程技术,不得不提及"进程"这个概念.百度百科对"进程"的解释如下: 进程(Process)是计算机中的程序 ...
- 《Java 多线程编程核心技术》- 笔记
作为业务开发人员,能够在工作中用到的技术其实不多.虽然平时老是说什么,多线程,并发,注入,攻击!但是在实际工作中,这些东西不见得用得上.因为,我们用的框架已经把这些事做掉了. 比如web开发,外面有大 ...
- Java多线程编程核心技术(二)对象及变量的并发访问
本文主要介绍Java多线程中的同步,也就是如何在Java语言中写出线程安全的程序,如何在Java语言中解决非线程安全的相关问题.阅读本文应该着重掌握如下技术点: synchronized对象监视器为O ...
- Java多线程编程核心技术(一)Java多线程技能
1.进程和线程 一个程序就是一个进程,而一个程序中的多个任务则被称为线程. 进程是表示资源分配的基本单位,线程是进程中执行运算的最小单位,亦是调度运行的基本单位. 举个例子: 打开你的计算机上的任务管 ...
- java多线程编程模式
前言 区别于java设计模式,下面介绍的是在多线程场景下,如何设计出合理的思路. 不可变对象模式 场景 1. 对象的变化频率不高 每一次变化就是一次深拷贝,会影响cpu以及gc,如果频繁操作会影响性能 ...
随机推荐
- WSL 2 内配置Fcitx自启动
前言 我通过配置成fcitx进行服务进行,但其权限是root,在普通模式下无法使用 我用的是xserver ( moba xterm),我要在gtk mode 下启动fcitx,其实 不用这么写 操作 ...
- vue3 ts遇到的问题
main.ts中的 createApp(App),只作用于一个,如果,有两个,则并不是一个对象,另一个会不生效
- git分支的一些处理情况记录
一.开发分支(dev)上的代码更新后,要合并到 master 分支 git checkout dev #切换到dev分支 git pull #将远程更新的代码同步到本地 git checkout ma ...
- Seal 0.4 发布:软件供应链安全洞察更上一层楼!
今天,我们很高兴宣布 Seal 0.4 已正式发布!在上一个版本中,Seal 完成了从单一产品到全链路平台的转变,通过全局视图帮助用户掌握软件开发生命周期各个环节的安全状况. 在 Seal 0.4 中 ...
- Quartz.NET 任务调度框架的demo实例
1.新建项目 简单实例,新建一个控制台程序 2.Nuget安装Quartz 3.编写代码 using Quartz; using Quartz.Impl; using Quartz.Logging; ...
- Xlight安装与使用
Xlight安装与使用 一.Xlight安装 下载Xlight安装包,点击安装,默认就可以,下一步 点击左上角增加虚拟服务器,IP地址为本机服务器IP地址 右键点击新添加的虚拟服务器,点击虚拟服务器操 ...
- 数字列表number,目标值target,找到number中两个不同数字之和等于target的数字,输出下标并顺序排列 ----笔试题记录扩展
一.思路: 输入:数字列表number,目标值target 判断条件:数字列表中两个不同数字相加等于target 输出:符合条件的两个数字的下标,下标顺序排列 方法1: def list(number ...
- selenium结合tenacity的retry实现验证码失败重试
说在前面 验证码登录的demo后续可以单独讲解,VIP学员对这部分应该都是掌握的,此处不再赘述 本文假设了一个场景 你通过OCR识别的验证码是有一定的错误几率的 本文是通过识别后的验证码去加一个随机字 ...
- Python:Excel自动化实践入门篇 甲【留言点赞领图书门票】
*以下内容为本人的学习笔记,如需要转载,请声明原文链接微信公众号「englyf」https://mp.weixin.qq.com/s?__biz=MzUxMTgxMzExNQ==&mid=22 ...
- Git基础操作及协作流程
一整套流程帮你实践整个 Git 操作基础流程. 来源:https://docs.microsoft.com/zh-cn/learn/paths/intro-to-vc-git/ Git 介绍 配置 G ...