Java内存模型(JMM)主要目标是定义多线程的情况下线程访问变量的规则。
JMM规定线程之间的共享变量存储在主内存中,每个线程都有一个本地内存(工作内存),本地内存存储了共享变量的副本。
volatile是一种轻量级的同步机制,可以保证可见性【及时将修改的变量刷新到主内存中】,但不能保证原子性,并且禁止重排序。
volatile在多线程下的适用场景:一写多读
volatile如何保证内存可见性?
当一个线程对volatile修饰的变量进行写操作时,该线程中的本地内存的变量会被立刻刷新到主内存中。
当一个线程对volatile修饰的变量进行读操作时,该线程直接读取主内存的变量。
volatile能否保证线程安全?
不能,保证线程安全需要同时具备原子性,可见性和有序性。而volatile只能保证可见性和有序性,无法保证原子性。
核心思想:在多线程执行同一个方法时,只有获取到锁,才能进入方法里面执行
使用方式:
轻量级锁:手动上锁解锁,扩展性强。代表:Lock
重量级锁:自动上锁解锁,封装程度高。代表:Synchronized
可重入锁(递归锁):当一个线程已经获取到锁后,再次请求该锁,就可直接获取。(锁的传递,锁的嵌套)代表:Synchronized,Lock
锁的可重入性避免了大部分死锁情况的产生
不可重入锁:不具备传递性
ReentrantReadWriteLock
相对Synchronized效率更高,但在多线程情况下,只支持读读共存,不支持读写,写写。
为什么乐观锁适合多读场景?
乐观锁是一种更新前的检查机制,相对于悲观锁来说在多读场景下可以减少锁的性能开销,对于多写场景,乐观锁会一直进入已修改,重新读取,再次提交的循环,反而带来更多的资源消耗。
【总的来说,乐观锁回滚重试,悲观锁阻塞事务】
原子类:AtomicBoolean,AtomicInteger,AtomicLong,AtomicReference可保证线程安全,底层使用CAS无锁机制
CAS:Compare and Swap,比较再交换,属于乐观锁的一种