编程-ReentrantLock

 

  前面我们已经学习过了

ObjectMonitor() {     _header       = NULL;     _count        = 0; //记录线程获取锁的次数    _waiters      = 0;     _recursions   = 0; //锁的重入次数    _object       = NULL;     _owner        = NULL;//指向持有ObjectMonitor对象的线程    _WaitSet      = NULL; //等待条件队列 类似AQS的ConditionObject    _WaitSetLock  = 0 ;     _Responsible  = NULL ;     _succ         = NULL ;     _cxq          = NULL ;     FreeNext      = NULL ;     _EntryList    = NULL ; //同步队列 类似AQS的CLH队列    _SpinFreq     = 0 ;     _SpinClock    = 0 ;     OwnerIsThread = 0 ;     _previous_owner_tid = 0;   }
复制代码

  从代码中可以看到synchronized实现的锁的重入依赖于JVM,JVM为每个对象的锁关联一个计数器_count和一个所有者线程_owner,当计数器为0的时候就认为锁没有被任何线程持有,当线程请求一个未被持有的锁时,JVM就记下锁的持有者,并将计数器的值设置为1,如果是同一个线程再次获取这个锁,计数器的值递增,而当线程退出时,计数器的值递减,直到计数器为0时,锁被释放。

  ReentrantLock实现了在内存语义上的synchronized,固然也是支持可重入的,那么ReentrantLock是如何支持的呢,让我们以非公平锁的实现看下ReentrantLock的可重入,代码如下:

复制代码
final boolean nonfairTryAcquire(int acquires) {             final Thread current = Thread.currentThread();//当前线程            int c = getState();             if (c == 0) {//表示锁未被抢占                if (compareAndSetState(0, acquires)) {//获取到同步状态                    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;         }          protected final boolean tryRelease(int releases) {             int c = getState() - releases; //既然可重入 就需要释放重入获取的锁            if (Thread.currentThread() != getExclusiveOwnerThread())                 throw new IllegalMonitorStateException();             boolean free = false;             if (c == 0) {                 free = true;//只有线程全部释放才返回true                setExclusiveOwnerThread(null); //同步队列的线程都可以去获取同步状态了            }             setState(c);              return free;         }
复制代码

  看到这也就明白了上文说的ReentrantLock类使用AQS同步状态来保存锁重复持有的次数。当锁被一个线程获取时,ReentrantLock也会记录下当前获得锁的线程标识,以便检查是否是重复获取,以及当错误的线程试图进行解锁操作时检测是否存在非法状态异常。

2.2 获取和释放锁

  如下是获取和释放锁的方法:

关键字:
50000+
5万行代码练就真实本领
17年
创办于2008年老牌培训机构
1000+
合作企业
98%
就业率

联系我们

电话咨询

0532-85025005

扫码添加微信