做同步java方法队列调用?

时间:2015-05-20 10:22:47

标签: java multithreading synchronized

我已经阅读了有关同步方法的oracle doc以及它们如何为多线程程序引入锁定,但有一件事我不清楚。 对已经锁定的方法的后续调用是否排队?

让我们说我们有一个班级:

class Astore {
    ...
    public synchronized void a() {
        doSomethingTimeConsuming();
    }
    ...
}

和3个调用astore.a()的线程

final Astore astore = new Astore();

Thread t1 = new Thread(new Runnable() {
    public void run() { 
        astore.a();
        doSomethingElse();
        astore.a();
    }
});
t1.start();

Thread t2 = new Thread(new Runnable() {
    public void run() {
        astore.a();
    }
});
t2.start();

Thread t3 = new Thread(new Runnable() {
    public void run() {
        astore.a();
    }
});
t3.start();

我不确定我是否正确地做了这个例子,但重点是,3个线程几乎同时使用synchronized方法调用同一个对象。

操作顺序是否存储在队列中,以便调用的线程为:

  1. t1(因为它被称为第一个)
  2. t2(在T1之后调用)
  3. T3
  4. 再次
  5. t1(当其他线程请求方法时,它正忙着用A做某事)
  6. 我可以安全地假设这将是行为,或者无法保证这将是顺序(或者更糟糕的是,t2和t3可能以随机顺序被调用)

    当多个线程可能需要共享数据时的最佳实践是什么(例如,每个活动连接有一个线程的套接字服务器 - 我不希望6个客户端在等待第一个完成巨大的任务时超时上传到共享数据结构)

3 个答案:

答案 0 :(得分:8)

不,它不会对该方法的调用进行排队。

如果调用是从已经获得锁定的线程(例如,递归调用)进行的,那么它将正常进行。

尝试让锁定能够进行调用的其他线程将保留在那里并等待锁定被释放。

订单无法保证,如果重要的话,请使用 fair ReentrantLock

答案 1 :(得分:2)

如果使用ReneterantLock而不是synchronized块,则可以设置一个fairness参数,以便当另一个线程释放锁时,等待最多的线程获得锁定,您可以阅读更多here

答案 2 :(得分:0)

folkol是正确的。

实际上它取决于机器的设计(CPU)

调用者应该等到资源由CPU分配。 然后CPU随机选择下一个调用者之一并为其分配资源并将其锁定(因为同步),直到第二个调用者完成其工作。