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

Wil*_*ill 5 java multithreading

如果我有一个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
        }

    }
}
Run Code Online (Sandbox Code Playgroud)

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

Viv*_*sse 8

不,他们没有按照他们的到达顺序执行.

执行顺序取决于与线程调度相关的大量参数,并且通常是不可预测的.


seh*_*seh 4

使用java.util.concurrent.locks.ReentrantLock,您可以指定与此处相关的公平策略。传递true给引用的构造函数请求锁“公平竞争”。这意味着什么在文档中有点模糊,但是研究底层AbstractQueuedSynchronizer类型ReentrantLock$FairSync的文档和(在 Sun JDK 中)的实现会给出额外的提示:

也就是说,当一个线程尝试以公平模式获取锁时,它不会“闯入”其他正在等待的线程之前;如果任何其他线程正在等待该锁,则新到达的线程将“获取该锁”。

现在,尽管不太可能,这个新排队的线程仍然有可能在其当前持有者下一次释放该锁时获取该锁,如果那时由于前辈被中断而恰好成为第一个排队的线程,但请观察尽管条件队列的逻辑模型是一等待线程,但在上述实现中,它实际上是一个队列CLH 队列,在论文The java.util.concurrent Synchronizer中的 Java 库应用中进行了描述)框架)。在公平模式下,只有队列中的第一项才会获取锁。

显然,两个线程在尝试“同时”获取锁时可能会发生竞争。使用公平锁,您可以预期,如果线程A首先到达并调用Lock#lock(),并且最终不得不等待,因为该锁由线程C持有,稍后线程B到达并调用,Lock#lock()而线程C仍持有该锁,则B将进入排在已经排队的A后面,一旦C释放锁,A将有机会先于B获取它。请参阅 中的实现,了解从 CLH 队列的头部到尾部的具体步骤。A将比B更靠近头部。AbstractQueuedSynchronizer$unparkSuccessor()

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

这项调查根据一项实施得出了一些结论。一般来说,采取巴鲁斯先生的观点更为安全:最好将采购订单视为从一组服务员中随机抓取。然而,通过对公平政策进行足够深入的研究,您可以看到其中存在一些决定论。不过,它并不是免费的。请注意禁止驳船时有关吞吐量下降的警告。