在Java中,显式锁获取顺序,在发信号的线程和最初获取锁的线程之间

时间:2014-01-16 17:32:48

标签: java multithreading locking

方法Condition.newCondition()的Javadoc声明“从等待方法返回的线程的锁重新获取的顺序与最初获取锁的线程的顺序相同,这是默认情况下未指定的,但是公平锁有利于那些等待时间最长的线程。

这是否意味着,使用显式锁定,从条件中唤醒的线程与最初获取它的线程一起竞争锁定获取,就像使用隐式锁定一样?

换句话说,拥有两组线程,一组试图第一次获得锁定,另一组试图在等待条件并发出信号后重新获取锁定,后者是后者锁定收购比前者更受青睐?

锁定公平性值是否会以任何方式影响这两个组的锁定获取顺序?

2 个答案:

答案 0 :(得分:2)

  

换句话说,拥有两组线程,一组试图第一次获得锁定,另一组试图在等待条件并发出信号后重新获取锁定,后者是后者锁定收购比前者更受青睐?

不,除非Lock是“公平的”,否则很可能相反:典型的实现有利于线程只是获取Lock,因为它让开头成功而不是放入线程睡觉,唤醒另一个。

  

锁定公平性值是否会以任何方式影响这两个组的锁定获取顺序?

不,锁定获取在那一点没有区别。当发出等待Condition的线程时,可能有其他线程等待第一次获取更长时间。并且“公平”Lock将更喜欢最长的等待线程。

答案 1 :(得分:0)

对于公平锁定,在单击后需要锁定的therad必须在锁定队列的末尾排队。

以下简短程序演示了此行为。

  • T1首先获取锁,然后在与此锁相关的条件上调用await。
  • T2然后获取锁并等待,直到T3试图获取锁,然后在条件下调用信号。
  • T3在等待T2持有的锁之前等待一段时间。

当T2调用信号时,T1尝试重新获取锁定。当T2释放锁定时,T1和T3都在竞争锁定,但T3首先获得锁定。

public class Test {

    public static void main(String[] args) throws Exception {
        final Lock r = new ReentrantLock(true);
        final Condition c = r.newCondition();

        Thread t1 = new Thread( () -> { 
            System.out.println("T1 try lock");
            r.lock(); 
            System.out.println("T1 got lock");
            System.out.println("T1 invokes await and releases lock");
            try { c.await(); } catch (InterruptedException e) { }
            System.out.println("T1 reqcquired lock");
            r.unlock();
        } );
        Thread t2 = new Thread( () -> {
            sleep(50);
            System.out.println("T2 try lock");
            r.lock();
            System.out.println("T2 got lock");
            sleep(100);
            c.signal();
            System.out.println("T2 signaled");
            sleep(100);
            r.unlock();
        } );
        Thread t3 = new Thread( () -> {
            sleep(100);
            System.out.println("T3 try lock");
            r.lock();
            System.out.println("T3 got lock");
            r.unlock();
        } );
        t1.start();
        t2.start();
        t3.start();
    }

    static void sleep(long millis) {
        try { Thread.sleep(millis); } catch (InterruptedException e) {  }
    }

}

输出

T1 try lock
T1 got lock
T1 invokes await and releases lock
T2 try lock
T2 got lock
T3 try lock
T2 signaled
T3 got lock
T1 got signal and reqcquired lock