volatile、synchronized和Lock
2018-01-29 本文已影响0人
lwz9103
一、 volatie
1.作用
保证了线程之间内存的可见性,且防止了指令重排序
2.什么叫做线程间内存不可见?JMM模型
image.png线程A 写入 x = x + 1(x初始值为0),先写到线程的工作内存(事实上是CPU高速缓存),然后再写到主内存。因此线程B在线程A更改x值后,仍然读取到原先的值。
3.什么叫做指令重排序?
单线程下,相互不依赖的指令之间,执行顺序是不确定的。
在多线程下,如果发生指令重排序,那么就会导致多线程语义错误。
image.png
执行顺序可能为 2 3 1 4
4.volatile底层操作
在写入变量的时候,JVM发送一条lock指令,在写操作在主内存上生效前,其他线程不能访问或者修改主内存该变量的值。
对此变量的操作是会防止指令重排序。
5.cas原理
使用volatile后,修改内存的中变量的值,并不是一个原子操作。比如x++就需要两步,先读变量x的值后更改x的值,因为在读x的值的时候,可能工作内存和主内存的值不一样,(因为读不加锁),出现这种情况后,需要重新获取主内存该变量的值,然后再进行设置变量的值。cas,如果主内存的值和预期值相等,则设置主内存的值,这两个操作是通过unsafe完成的,是一个原子操作。
5.原子变量及使用场景
AtomicLong (id生成器,UUID)
二、synchronized
1、性质
- 内存可见性
对对象的更改对其他线程可见 - 互斥性
同一时间只有一个线程能获取到对象的monitor(锁) - 可重入性
持有对象monitor的线程可以再次获得该对象的monitor
2.sychronzied原理
monitor模型三、Lock
1.ReentrantLock(可重入锁,默认非公平策略)
1.1 公平锁(CAS)
公平锁1.2 非公平锁(CAS)
非公平锁2.ReentrantReadWriteLock(读写锁)
读共享,写互斥:读的时候不允许写,但允许读,写的时候不允许写也不允许读
3.数据库中的 悲观锁和乐观锁
+悲观锁
读锁,写锁都是写锁,悲观锁认为在读取或者修改数据时,数据可能会被其他线程修改,因此在读取或者写入前先加锁,再进行操作。
+乐观锁
类似于CAS,乐观锁认为在修改数据的时候,其他线程不会做修改,但在写入数据前,会先比较预期值和真实数据是否一致,如果不一致,会重新获取数据,再写入。