如果两个线程正在等待进入同步方法,那么当互斥锁被释放时,它们是按照它们到达的顺序执行的吗?

如果我有一个synchronized方法并且有两个线程正在等待输入它们,则它们似乎进入Last In First Executed线程.有没有办法让这首先被执行?

这是我正在使用的单元测试:

package com.test.thread;

import org.apache.log4j.Logger;
import org.junit.Test;

public class ThreadTest {
    private static final Logger log = Logger.getLogger(ThreadTest.class);

    @Test
    public void testThreading() throws InterruptedException {
        Thread t1 = new Thread(new Runnable() {    
            public void run() { synchd("1"); }
        });
        Thread t2 = new Thread(new Runnable() {    
            public void run() { synchd("2"); }
        });
        Thread t3 = new Thread(new Runnable() {    
            public void run() { synchd("3"); }
        });

        t3.start();
        Thread.sleep(5);
        t1.start();
        t2.start();

        Thread.sleep(12000);
    }

    public static synchronized void synchd(String output) {
        log.debug(output);
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            // do nothing
        }

    }
}

这个输出总是3,2,1,我想找到一个方法,它是3,1,2.

最佳答案
使用java.util.concurrent.locks.ReentrantLock,您可以指定与此相关的公平政策.将true传递给引用的构造函数请求锁定“公平”.这意味着在文档中有点模糊,但研究the underlying AbstractQueuedSynchronizer type的文档和ReentrantLock $FairSync(在Sun JDK中)的实现提供了额外的提示:

Namely, when one thread attempts to acquire the lock in fair mode, it will not “barge” ahead of other waiting threads; if any other threads are waiting for the lock, the newly arriving thread will “get it line.”

现在,仍然有可能 – 虽然极不可能 – 这个新排队的线程将在下一次由其当前持有者释放时获取锁定,如果它由于前任被中断而恰好成为第一线,但观察尽管条件队列的逻辑模型是一组等待线程,但在上述实现中,它实际上是一个队列(CLH队列,在其文件The java.util.concurrent Synchronizer Framework中对Java库的应用中描述).在公平模式下,只有队列中的第一个项目才能获得锁定.

显然,当试图“同时”获取锁时,两个线程可能会竞争.使用公平锁定,你可以预期如果线程A首先到达并调用Lock#lock(),并且最终必须等待,因为锁由线程C保持,后来线程B到达并调用Lock#lock()而线程C仍然保持它,B将在已经排队的A后面排队,并且一旦C释放锁定,A将在B获得它之前获得机会.请参阅AbstractQueuedSynchronizer $unparkSuccessor()中的实现,以了解从CLH队列的头部向其尾部的特定前进. A比B更接近头部.

ReentrantLock的文档警告说,即使在公平模式下运行,已经等待锁的线程也可能会丢失到当前持有锁的线程释放它并再次获取它.我认为 – 但不确定 – 当当前线程在尚未落入队列的其他线程之前获胜时会发生这种情况.另请注意有关ReentrantLock#tryLock()的警告;与定时的ReentrantLock#tryLock(long,TimeUnit)不同,前者不尊重公平政策.

该调查基于一种实施方式得出一些结论.一般来说,采取Mr. Barousse’s view会更安全:收购订单最好被认为是来自一组服务员的随机抓取.但是,如果对公平政策进行深入研究,你会发现存在一些决定论.但它不是免费的;请注意禁止在驳船时减少吞吐量的警告.

转载注明原文:如果两个线程正在等待进入同步方法,那么当互斥锁被释放时,它们是按照它们到达的顺序执行的吗? - 代码日志