JUC之ReetrantLock

lock()

//获取锁,一直等待锁可用
 public void lock() 
 {
        sync.lock();
 }
 //公平锁获取
 final void lock() 
 {
            acquire(1);
 }
 //非公平锁的获取
  final void lock() 
  {
            if (compareAndSetState(0, 1))
                setExclusiveOwnerThread(Thread.currentThread());
            else
                acquire(1);
  }

FairSync.tryAcquire

函数的执行流程:
(1)如果当前锁状态state为0,说明锁处于闲置状态可以被获取。首先调用hasQueuedPredecessors判断当前线程是否还有前驱节点在等待获取锁。如果没有,直接返回false;没有的情况下,通过调用compareAndSetState(CAS)修改state值来标记自己已经拿到锁,CAS执行成功后调用setExclusiveOwnerThread设置锁的持有者为当前线程。程序执行到现在说明锁获取成功,返回true;
(2)如果当前锁状态state不为0,但当前线程已经持有锁(current == getExclusiveOwnerThread()),由于锁是可重入(多次获取)的,则更新重入后的锁状态state += acquires 。锁获取成功返回true。

 protected final boolean tryAcquire(int acquires) 
 {
            final Thread current = Thread.currentThread();
            //获取锁状态
            int c = getState();
            if (c == 0) 
            {
                if (!hasQueuedPredecessors() &&   //判断当前线程是否还有前节点
                    compareAndSetState(0, acquires)) //CAS方法修改state
                    {
                    		//获取锁成功,设置锁的持有线程为当前线程
		                    setExclusiveOwnerThread(current);
        		            return true;
                }
            }
            // 已经持有锁
            else if (current == getExclusiveOwnerThread()) 
            {
               //重入
                int nextc = c + acquires;
                if (nextc < 0)
                    throw new Error("Maximum lock count exceeded");
                //更新state的状态
                setState(nextc);
                return true;
            }
            return false;
 }

NonFairSync.tryAcquire

 protected final boolean tryAcquire(int acquires) 
 {
            return nonfairTryAcquire(acquires);
 }
 
 final boolean nonfairTryAcquire(int acquires) 
 {
            final Thread current = Thread.currentThread();
            int c = getState();
            if (c == 0) 
            {
                if (compareAndSetState(0, acquires))  //CAS修改state
                {
                    setExclusiveOwnerThread(current);
                	    return true;
                }
            }
            else if (current == getExclusiveOwnerThread()) 
            {
                int nextc = c + acquires;
                if (nextc < 0) // overflow
                    throw new Error("Maximum lock count exceeded");
                setState(nextc);
                return true;
            }
            return false;
 }

Note: 通过对比公平锁和非公平锁tryAcquire的代码可以看到,非公平锁的获取略去了!hasQueuedPredecessors()这一操作,也就是说它不会判断当前线程是否还有前节点(prev node)在等待获取锁,而是直接去进行锁获取操作。

unlock

//释放锁
public void unlock() 
{
    sync.release(1);
}

tryRelease

        protected final boolean tryRelease(int releases) 
        {
            // 计算释放后的state的值
            int c = getState() - releases;
            if (Thread.currentThread() != getExclusiveOwnerThread())
                throw new IllegalMonitorStateException();
            boolean free = false;
            if (c == 0) 
            {
                //锁全部释放,可以唤醒下一个等待线程
                free = true;
                //设置锁持有线程为null
                setExclusiveOwnerThread(null);
            }
            setState(c);
            return free;
        }

Note: tryRelease用于释放给定量的资源。在ReetrantLock中每次释放量为1,也就是说,在可重入锁中,获取锁的次数必须要等于释放锁的次数,这样才算是真正释放了锁。在锁全部释放后(state==0)才可以唤醒下一个等待线程。

等待条件Condition

Condition接口和AQS对Condition接口的实现

synchronized和ReentrantLock的选择

ReentrantLock在加锁和内存上提供的语义与内置锁synchronized相同,此外它还提供了一些其他功能,包括定时的锁等待、可中断的锁等待、公平性,以及实现非块结构的加锁。从性能方面来说,在JDK5的早期版本中,ReentrantLock的性能远远好于synchronized,但是从JDK6开始,JDK在synchronized上做了大量优化,使得两者的性能差距不大。synchronized的优点就是简洁。 所以说,两者之间的选择还是要看具体的需求,ReentrantLock可以作为一种高级工具,当需要一些高级功能时可以使用它。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值