当前位置:编程学习 > JAVA >>

关于多线程同步的初步教程--可重入锁的设计及使用

    上一篇中的Mutex是一个独占锁,只能有一个线程拥有该锁,并且即时是同一个线程,如果已经持有一个Mutex时,再次企图获取该锁时仍然会阻塞。有的时候我们需要锁能够像Java语言的synchronized那样,同一个线程可以重新进入,只要已经拥有了该锁,而不用在该锁上阻塞。我们可以对上篇中的Mutex的实现进行改造,实现一个可重入的锁--ReentrantLock。这需要ReentrantLock中记录当前锁的拥有者(线程),同时设置一个整型变量,记录当前线程进入的次数。

  1. public class ReentrantLock implements Sync  {
  2.   protected Thread owner_ = null;
  3.   protected long holds_ = 0;
  4.   //......
  5. }

在获取、释放锁时,首先判断该线程是否是锁的拥有者。如果是当前线程已经拥有该锁,则在每一次acquire()时增1,在release()时减1在次数减少到0时,说明该锁的当前拥有者已经完全释放该锁,不再拥有该锁。所以,将拥有者设置为null。如果当前线程不是锁的拥有者,那么在企图获取锁时在该锁上wait(),在release()方法中,如果拥有者已经完全释放锁,那么就将拥有者清零,并notify()其它线程。

  1.   public void acquire() throws InterruptedException {
  2.     if (Thread.interrupted()) throw new InterruptedException();
  3.     Thread caller = Thread.currentThread();
  4.     synchronized(this) { // 在this上同步
  5.       if (caller == owner_) 
  6.         ++holds_;
  7.       else {
  8.         try {  
  9.           while (owner_ != null) wait(); 
  10.           owner_ = caller;
  11.           holds_ = 1;
  12.         }
  13.         catch (InterruptedException ex) {
  14.           notify();
  15.           throw ex;
  16.         }
  17.       }
  18.     }
  19.   }
  20.   public synchronized void release()  { //在this上同步
  21.     if (Thread.currentThread() != owner_)
  22.       throw new Error("Illegal Lock usage"); 
  23.     if (--holds_ == 0) {
  24.       owner_ = null;
  25.       notify(); 
  26.     }
  27.   }


注意上面的代码要对owner_和holds_在this上进行同步,以解决在这两个变量上的竞态条件。attempt()方法实现和Mutex类似,也添加了锁拥有者的检查及计数:

  1.   public boolean attempt(long msecs) throws InterruptedException {
  2.     if (Thread.interrupted()) throw new InterruptedException();
  3.     Thread caller = Thread.currentThread();
  4.     synchronized(this) {
  5.       if (caller == owner_) {
  6.         ++holds_;
  7.         return true;
  8.       }
  9.       else if (owner_ == null) {
  10.         owner_ = caller;
  11.         holds_ = 1;
  12.         return true;
  13.       }
  14.       else if (msecs <=&nb
补充:软件开发 , Java ,
CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,