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,如果频繁操作会影响性能 ...
随机推荐
- 企业级GitLab在Docker部署使用
一.部署gitlab 这里使用的是Centos8,安装Docker环境 ,这里不说了,参考:https://www.cnblogs.com/wei325/p/15139701.html gitlab有 ...
- RabbitMQ.Client.Exceptions.BrokerUnreachableException:“None of the specified endpoints were reachabl
1.问题复现 RabbitMQ新建账户进行具体操作时报如题错误,没有一个指定的端点是可到达的 2.解决办法 ① 控制台命令进入sbin所在文件夹 ② 输入命令设置权限 rabbitmqctl set_ ...
- C端自动化实现:appium+winappdriver+python
一. 前言 有小伙伴有办公自动化的需求,特此出一篇C端自动化教程,并附带demo案例.C端的自动化比B端多一个appium,其他的操作大同小异. 二. 环境 appium:exe工具,用于启动服务,官 ...
- P6329 【模板】点分树 | 震波
\(\text{Solution}\) 点分树就是将点分治过程中的重心连成一棵虚树 对点分树子树信息的记录,就是点分治处理每个重心时需要的信息 这样就可以留下点分治的过程,支持多次修改和查询 点分树树 ...
- What?JMeter做UI自动化!
JMeter做UI自动化 不推荐,好别扭,但可行 插件安装 搜插件selenium,安装 添加config 添加线程组 右键线程组->添加->配置元件->jp@gc - Chrome ...
- html+css+js实现一个简易日历
0.效果预览 只实现了日历最基础的功能,当前日期红色显示,可通过上方的左右按钮查看上一月或下一月的日期. 1.HTML部分 1 <body> 2 <div id="cldF ...
- php使用PDO获取结果集的方法
php使用PDO获取结果集的方法 转载:https://www.jb51.net/article/105797.htm 更新时间:2017年02月16日 11:11:42 作者:水晶依恋 ...
- go语言环境配置(windous)
1.下载go语言安装包:https://golang.google.cn/dl/ 2.配置环境变量:GOBIN:项目bin目录 GOPATH:项目目录(src下) GOROOT(go的环境变量) G ...
- 使用AJAX绑定点击事件将接口值返回渲染到指定位置
AJAX 是局部的刷新或者叫做无刷新技术 首先是js部分,这里注意不紧要引入express模块,还需要把cors模块也引入 在下面添加了判断,用来判断所取得的随机值是否在0.5以上 接下来是HTML部 ...
- JavaScript验证API
验证API 两个方法: checkValidity():如果input元素中的数据是合法的返回true,否则返回false: setCustomValidity():设置input元素的validat ...