java基础篇(4)——java中的锁

java中有两种显试锁:synchronized和Lock接口。

synchronized的实现原理

        synchronized可以保证方法或者代码块在运行时,同一时刻只有一个方法可以进入到临界区,同时它还可以保证共享变量的内存可见性
Java中每一个对象都可以作为锁,这是synchronized实现同步的基础: 
1. 普通同步方法,锁是当前实例对象 
2. 静态同步方法,锁是当前类的class对象 

3. 同步方法块,锁是括号里面的对象

    当一个线程访问同步代码块时,它首先是需要得到锁才能执行同步代码,当退出或者抛出异常时必须要释放锁。

    同步代码块是使用monitorenter和monitorexit指令实现的,同步方法(在这看不出来需要看JVM底层实现)依靠的是方法修饰符上的ACC_SYNCHRONIZED实现。 

同步代码块:monitorenter指令插入到同步代码块的开始位置,monitorexit指令插入到同步代码块的结束位置,JVM需要保证每一个monitorenter都有一个monitorexit与之相对应。任何对象都有一个monitor与之相关联,当且一个monitor被持有之后,他将处于锁定状态。线程执行到monitorenter指令时,将会尝试获取对象所对应的monitor所有权,即尝试获取对象的锁; 
同步方法:synchronized方法则会被翻译成普通的方法调用和返回指令如:invokevirtual、areturn指令,在VM字节码层面并没有任何特别的指令来实现被synchronized修饰的方法,而是在Class文件的方法表中将该方法的access_flags字段中的synchronized标志位置1,表示该方法是同步方法并使用调用该方法的对象或该方法所属的Class在JVM的内部对象表示Klass做为锁对象。

参考:深入分析synchronized的实现原理

Lock接口

我们常用的Lock接口的实现类是,ReentrantLock。

ReentrantLock是一种可重入锁,可以实现公平锁和非公平锁;ReentrantLock是一种悲观锁,但它是用乐观锁CAS和volatile实现。

解释:

可重入锁:所谓可重入锁既一个线程在已经持有一个锁的情况下,它可以再次或多次(重复)进入该锁锁定的代码块。每个锁都有一个锁定计数器,当一个个线程获取一个锁时,该锁的计数器+1,退出时计数器-1。当且仅当计数器为0时,该线程才完全退出该锁锁定的代码块。

         当一个线程拿到锁定一个对象,怎么知道这个线程能不能重入锁这个对象呢?或者说,怎么知道一个线程是否持有一个对象呢
有方法可以判断某个线程是否持有对象监视器:Thread类提供了一个holdsLock(Object obj)方法,当且仅当对象obj的监视器被某条线程持有的时候才会返回true,注意这是一个static方法,这意味着"某条线程"指的是当前线程。

公平锁/非公平锁公平和非公平锁的队列都基于锁内部维护的一个双向链表,链表的Node的值既每一个尝试获取该锁的线程。

公平锁既最后到达的线程放在队列的末尾,每次都去队头的节点获得锁。

非公平锁既,当线程队列等待过程中有新的线程进入,新的线程会尝试获取锁,并且有一定的几率获取的到锁,而导致排队的线程不能获取到锁。所以是非公平的。

悲观锁:所谓悲观锁,既线程每次修改数据时都认为会发生冲突,所以直接锁定一块区域,防止修改冲突。我们常用的锁synchronized,ReentrantLock都是悲观锁。

乐观锁:所谓乐观锁既认为自己操作的过程中不会发生冲突,直接去操作。如果发生了冲突就放弃原先的操作重新操作。一般都是通过版本号控制的。CAS就是一种乐观锁的实现。

CAS(compare and swap)的实现思想:CAS是java中的一个乐观锁实现。

CAS的ABA问题解决方案:因为CAS需要在操作值的时候检查下值有没有发生变化,如果没有发生变化则更新,但是如果一个值原来是A,变成了B,又变成了A,那么使用CAS进行检查时会发现它的值没有发生变化,但是实际上却变化了。ABA问题的解决思路就是使用版本号。在变量前面追加上版本号,每次变量更新的时候把版本号加一,那么A-B-A 就会变成1A-2B-3A。

了解更多:Java中CAS详解

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值