JVM虚拟机规范学习笔记
ThreadLocal
当一个变量想要多线程共享时我们可以用volatile修饰,当一个变量我们只想让所拥有的线程自己访问时,可以将其存入到ThreadLocal里面。通过get和set的方法进行存取。
每个Thread都有一个ThreadLocalMap对象,这个对象里面以threadLocalhashCode为k,要存储的变量为v存储。而ThreadLocal对象实例就是我们访问它的入口。
线程安全的实现方案:
1、互斥同步
他是常见的一种并发正确性保障手段。同步是指多个线程并发访问共享数据时,保证共享数据在同一个时刻只被线程使用。互斥是实现同步的一种手段。临界区、互斥量、信号量都是主要的互斥实现方式。
即我们想要同步的目的,我们可以使用互斥来实现(互斥是方法,同步是目的)。
Synchronized
ReentrantLock
它增加了一些高级功能:等待可中断、可实现公平锁、以及锁可以绑定多个条件。
2、非阻塞同步
3、无同步方案
要保证线程安全,并不是一定就要进行同步,两者没有因果关系。同步只是保证共享数据争用时的正确手段,如果一个方法本身就不涉及共享数据,那它自然就无须任何同步操作去保证正确性。
1、可重入代码
2、线程本地存储
锁优化
自旋锁和自适应自旋
根据前一次在同一个锁上的自旋时间及锁的拥有者的状态来决定,例如一个门锁用许多钥匙都能打开,我上次去开锁一下子就打开了,那么我这次去开锁的时候,即使看到别人已经占用了锁,打开了,但是我还是会等待一段时间,尝试去开锁。而另外一个门锁,是密码锁,只有几个人知道密码,上次我去开锁的时候就失败了,我知道自己有很大的概率打不开,就不去尝试开这个锁。
锁消除
判断依据主要来源于逃逸分析的数据支持。例如String的concatString方法。在jdk1.5后使用StringBuffer的append的方法进行动态拼接。因为StringBuffer对象只能在这个concatString方法里面使用,不会逃逸到其他地方,就会把StringBuffer的锁给消除掉。
锁粗化
还是上面的String的concatString方法中的StringBuffer的连续append,当虚拟机检测到一串零碎的操作都对同一个对象加锁,将会把加锁同步的范围扩展到整个操作序列的外部,就是扩展到第一个append()操作之前直至最后一个append()操作之后,就只需要加一次锁就可以了。
步的范围扩展到整个操作序列的外部,就是扩展到第一个append()操作之前直至最后一个append()操作之后,就只需要加一次锁就可以了。