ReentrantLock - 在被调用的方法中解锁

ReentrantLock - unlocking in called method

ReentrantLock

void a() {

    lock.lock();    //got intrinsic lock 
    System.out.println(Thread.currentThread().getName());
    System.out.println("In A");
    b();            // called method in synchronized block

    Thread.sleep(2000);    // sleeping current thread(avoided try catch for simplicity) 


    System.out.println("after calling method B()");
    System.out.println(Thread.currentThread().getName());

    lock.unlock();    // releasing intrinsic lock

}

void b() {

    lock.lock();// getting intrinsic lock, no problem as calling thread already has intrinsic lock 
    System.out.println(Thread.currentThread().getName());
    System.out.println("In B");
    lock.unlock();    // intentionally releasing lock, so now there is no lock .

        Thread.sleep(2000);
}

生成了两个线程 Thread-0 和 Thread-1 都在调用 a()。

在 a() 中,我正在获取内在锁,然后调用 b()。在 b() 中,我也获得了内部锁,所以我将获得当前线程拥有的相同锁。 现在我有意在 b() 中解锁,它释放了锁,以便其他等待线程可以获得锁,只是为了确保我什至让当前线程 sleep 。当我的线程在 b() 中休眠 2000 毫秒而不是在 a() 中休眠 2000 毫秒时,我期望其他线程会 运行 a() 通过获取已释放的锁。

但我的输出没有发生

输出:-

Thread-0
In A
Thread-0
In B
after calling method B()
Thread-0
Thread-1
In A
Thread-1
In B
after calling method B()
Thread-1

Now I'm intentionally unlocking in b() which releases the lock so that other waiting thread could get the lock

不,它没有完全释放它 - 它只是减少锁定计数。在调用 unlock 之前,您已经调用了 lock 两次 ,因此保持计数为 2。在调用 unlock 之后,保持计数为1,所以它仍然在阻止其他线程获取锁。基本上,您的代码有点像:

void a() {
    synchronized (foo) {
        b();
    }
}

void b() {
    synchronized(foo) {
        // In here, the count is 2
    }
    // Now the count is still 1...
}

很重要的是要理解锁class的名字是ReentrantLock,意思是同一个Thread可以多次获取锁,但是必须释放相同的次数才能退出监视器。

在 Java-8 中引入了另一个名为 StampedLock 的锁 class,它不是可重入的,并且会有不同的行为。