Java同步之Lock

之前说过,Java是在高并发的过程中实现同步的方式有synchronized和Lock两种方式,这篇主要是介绍Lock的实现同步的原理,和相关的具体实现类和常用方法.

Lock实现锁的原理主要就是通过代码来实现的,阻塞功能就是通过自旋锁和链表来实现的,其中通过state状态字段来判断该代码块的锁是否已经被其他线程占有.

首先我们先分析源码,来理解Lock是如何实现同步功能的.我们主要通过ReentrantLock来分析

1,该类实现了Lock接口和Serializable接口.所以该类实现了Lock的所有方法.

从该类的构造器中可以看出ReentrantLock可以实现公平锁和非公平锁.不传参数的话默认生成非公平锁,调用的lock()方法,里面都是公平锁或非公平锁实现的lock()方法.



下面是公平锁和非公平锁(第二个是非公平锁)实现的lock的方法源码,可以看出非公平锁多了一个步骤CAS,该方法就是相当于插队的形式,先去该类的内存中去查看state变量是不是为0了,如果是0 了就把state设置为1,后面再执行条件里的方法,把插队的线程设为正在执行代码块的线程.



我们先看一下非公平锁里不同的方法部分compareAndSetState()方法和setExclusiveOwnerThread()方法

1,compareAndSetState():进入该方法可以看出方法执行了unsafe的CAS(简称)方法.该方法是native方法

关于这个方法的详细解释:https://www.cnblogs.com/xrq730/p/4976007.html

可以通过此链接了解.该方法提供的是硬件级别的原子操作,在高并发的情况下也实现了同步结果,但效率比一般的锁要高

CAS有三个操作数:内存值V、旧的预期值A、要修改的值B,当且仅当预期值A和内存值V相同时,将内存值修改为B并返回true,否则什么都不做并返回false

stateOffset就是内存值v,表示的是变量值在内存中的偏移地址,因为Unsafe就是根据内存偏移地址获取数据的原值的

expect就是预期值A,update就是修改值B.


如果返回true则意味着线程抢到Lock锁了,就执行到下一个方法setExclusiveOwnerThread():该方法比较简单,就是把这个线程赋值给正在使用的线程变量.执行这个变量主要是在后面unlock释放锁的时候用了判断是不是同一个线程,如果不是则回抛出异常,具体在后面分析unlock方法源码时可以详细了解.


上面两个方法实现了,就使得线程竞争锁成功了,总结:其实非公平锁就是进来就直接去获取锁的资源,其实就是通过CAS方法去尝试改变state状态,如果成功了就插队成功,失败的话,就会执行acquire方法.公平锁和非公平锁的具体实现还是有部分区别的.

下面我们在来看acquire()获取锁方法:进入源码可以看出里面有三个小方法组成.且传入的参数都是1,

tryacquire()该方法是尝试获取锁,如果获取到锁了就会返回true,没有则false

addWaiter():该方法传入的参数是独占锁的标志(即为null源码中有显示).将该线程加入到等待队列的队尾,并返回该线程的节点

acquireQueued():该方法传入的参数是等待队列的当前节点和1,里面通过自旋锁的方式实现线程的等待过程,直到该线程获取到锁后,会返回该线程是否在等待过程中是否被中断,如果接受到中断信息则返回true,否则false.

selfinterrupt():该方法就是执行下该线程的interrupt方法,重新发送下中断信息,因为在自循环中,该线程是等待的,是不会处理中断方法的,所以在重新发送一次


这几个方法都是AQS(AbstractQueuedSynchronize抽象对象队列同步器)类里面实现的功能.

详情https://www.cnblogs.com/daydaynobug/p/6752837.html

总结:在ReentrantLock实现获取锁的过程中:主要用到的是CAS(硬件级别的代码操作实现state状态字段的同步性),AQS(通过自旋锁实现线程的等待功能,队列实现队列的排队功能)

unlock()

下面我们在看看解锁方法unlock():从源码中可以看出,该方法就是对state值的操作,因为ReentrantLock是可重入锁,所以state值可能大于1,当state为0 的时候,才会返回true,同时把持有锁线程设为null.执行该方法时,如果不是锁持有线程会抛出异常.



总结:ReentrantLock在实现锁的功能主要就是通过State状态来做相应处理的,里面应用了CAS功能,AQS功能,自旋锁,队列等其他方法.

下面在说一下该类中其他方法的功能和实现:

1trylock():

该方法会返回一个Boolean值,true则表示已经获取到锁,false则未获取到锁.该发方法就是尝试一次获取锁,通过不同的结果判断去做不同的处理,有时候线程获取不到锁,可以不用非要去排队等待,也可以先去做其他业务处理,回头在来处理.



newCondition():该方法返回的是一个Condition实体

具体使用:通过下面的截图我们可以看出它主要实现了是wait方法和signal方法.其实该方法代替的就是Object的wait和notify();

lockInterruptibly():该方法是获取锁的另一种方式,就是在获取的过程中,如果线程被执行了interrupt()方法,则回抛出InterruptedException异常,终止获取锁进入异常处理状态,且在抛出异常前会把终止状态清空,变为未获取终止信号.

通过源码可以看出,都是通过Thread.interrupted()的方法来判断是否有中断请求的.










  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值