JVM——线程安全的实现方法

一互斥同步(悲观的并发策略)

同步是指在多个线程并发访问共享数据时,保证共享数据在同一时刻只被一个线程使用。互斥是实现同步的一种手段,下面介绍两种互斥同步的手段:synchronized关键字和concurrent包中的重入锁ReentrantLock

synchronized关键字:

synchronized关键字经过编译之后,会在同步块的前后分别形成monitorenter和monitorexit两个字节码指令,这两个字节码都需要一个reference类型的参数来指明要锁定和解锁的对象。如果Java程序中的synchronized明确指定了对象参数,那就是这个对象的reference,如果没有明确执行,根据synchronized修饰的是实例方法还是类方法,去取对应的实例对象或Class对象作为锁对象。

ps:synchronized同步块对同一条线程来说是可重入的,(锁是可以重入的)

同步块在已进入的线程执行完之间,会阻塞后面的其他线程进入。

ReentrantLock:

相比synchronized,ReentrantLock增加了一些高级功能:

  1. 等待可中断是指当持有所的线程长期不释放锁的时候,正在等待的线程可以选择放弃等待,改为处理其他事情,可中断性对处理执行时间非常长的同步块很有帮助
  2. 公平锁是指在多个线程在等待同一个锁时,必须按照申请锁的时间顺序来依次获得锁。
  3. 锁绑定多个条件是指一个ReentrantLock对象可以同时绑定多个Condition对象,而在synchronized中只能实现一个条件

总结:在synchronized能实现需求的情况下,优先考虑使用synchronized进行同步

二非阻塞同步(乐观的并发策略)

基于冲突检测的乐观的并发策略,先进行操作,如果没有其他线程争用共享数据,那操作就成功了;如果共享数据由争用,产生了冲突,那就再采取其他的补偿措施

一般靠硬件来实现操作和冲突检测这两个步骤具有原子性,常用的指令:CAS

三无同步方案

可重入代码:这种代码也叫做春代码,可以在代码执行的任何时刻中断它,转而去执行另外一段代码,而在控制权返回后,原来的程序不会出现任何错误。相对于线程安全来说,可重入性是更基本的特性,它可以保证线程安全,即所有的可重入代码都是线程安全的,但是并非所有的线程安全的代码都是可重入的。

线程本地存储:如果一段代码中所需要的数据必须与其他代码共享,那就看看这些共享数据的代码能否在同一个线程中执行?如果能保证,我们就可以把共享数据的可见范围限制在同一个线程之内,这样无需同步也能保证线程之间不出现数据争用的问题。

总结:

Java语言中,如果一个变量要被多个线程访问,可以使用volatile关键字声明它为“易变的”;如果一个变量要被某个线程独享,可以通过java.lang.ThreadLocal类来实现线程本地存储的功能。

猜你喜欢

转载自blog.csdn.net/wo8vqj68/article/details/82918448
今日推荐