原子性
原则性,即一个操作或者多个操作要么全部执行,要么都不执行
可见性
可见性是指多个线程访问同一变量时,一个线程修改了这个变量的值,其他线程能够立即看到修改的值,对于单线程来说,这不是问题.
有序性
有序性即程序执行的顺序按照代码的先后顺序执行.
多线程控制类
为了保证多线程的三个特性,java引入了很多线程控制机制,如下:
ThreadLocal
ThreadLocal提供线程局部变量,即为使用相同变量的每一个线程维护一个该变量的副本.
常用方法:
initialValue:创建副本方法
get:获取副本方法
set:设置副本方法
分析:
原子类
Java的java.util.concurent.atomic包里提供了很多可以进行原子操作的类分为一下四类:
提供这些原子类的目的就是为了解决基本类型操作的非原子性导致多线程并发出现的问题.
非原子性操作问题演示
非原子性的操作会引发什么问题?
i++并不是原子操作;所以多线程情况下就会出现问题
可以使用原子类解决非原子性操作问题
AtonicInteger类可以保证++操作的原子性
原子类CAS原理分析
CAS的ABA问题即解决
ABA问题分析
当前内存的值一开始是A,被另外一个线程先改为B然后再该为A,那么当前线程访问的时候发现是啊\A,则认为它没有被其他线程访问过.
在某些场景下这是存在错误风险的如下图:
ABA问题解决
Lock接口
Lock和ReadWriteLock是两大锁的根接口
Lock接口支持重入,公平等的锁规则:
实现类:ReentrantLock,ReadLock和WriteLock.
ReadWriteLock接口定义读取者共享而写入者独占的锁
实现类:ReentrantReadWriteLock
可重入锁(ReentrantLock)
不可重入锁,即线程请求它已经拥有的锁时会阻塞.
可重入锁,即线程可以进入它已经拥有的锁的同步代码块
读写锁(ReentrantReadWriteLock)
读写锁,即可以同时读,不能同时写;读的时候不能写,写的时候不能读.
读操作
写操作
Volatile关键字
作用
一个共享变量(类的成员变量,类的静态变量)被volatile修饰后,那么就具备了两层语义:
保证了不同线程对这个变量进行操作时的可见性,即一个线程修改了某个变量的值,这新值对其他线程来说是立即可见的.(注意:不保证原子性)
禁止进行指令重排序.(保证变量所在行的有序性)
重排序即:
int i; i=1;i=2i=3
java会忽略前两个赋值,即重排序
加了volatile则老老实实一个一个执行过来,java不会进行优化
应用场景
基于volatile的作用,使用volatile必须满足一下两个条件:
对变量的写操作不依赖于当前值
该变量没有包含在具体有其他变量的不变式中