3

发生了一些奇怪的事情。当我进入同步块时,我尝试打印线程的名称。在打印语句之后,我暂停了 100000 秒。

@Override
public int getNextAvailableVm() {
    synchronized(this) {

        System.out.println(Thread.currentThread().getName());

        try {Thread.sleep(100000000);}catch(Exception exc){}

        String dataCenter = dcc.getDataCenterName();
        int totalVMs = Temp_Algo_Static_Var.vmCountMap.get(dataCenter);
        AlgoHelper ah = (AlgoHelper)Temp_Algo_Static_Var.map.get(dataCenter);
        .
        .
        .
   }
}

但是在运行此方法时,会打印 2 个线程的名称。

Thread-11
Thread-13

在此之后,出现了长时间的停顿。这是为什么 ?当第一个线程尚未离开块时,两个线程如何进入同步块?

4

3 回答 3

6

如果两个线程针对同一个对象运行,那么这不应该发生。

因此,我建议您为每个线程创建一个新对象,或者至少有一些线程在不同的对象上运行。

如果你确实想要多个对象,那么你不应该使用synchronized(this)你应该创建一个static final Objectto synchronizeon。请不要同步,this.getClass()因为它会中断。

于 2013-09-09T10:58:07.367 回答
1

您很可能正在调用getNextAvailableVm()包含类的不同实例。由于您正在同步,this您将锁定两个不同的监视器(第一个线程锁定在 instance1 上,第二个线程锁定在 instance2 上)。

有很多方法可以纠正这个问题:

  • 制作整个方法synchronized
  • 同步this.getClass()
  • 定义要锁定的静态对象
  • 使用 java.util.concurrent.locks 中的方法进行锁定

这些只是解决您的问题的一些建议,但要找到正确的建议,我们必须更多地了解您的应用程序结构和您的要求。

于 2013-09-09T11:00:03.957 回答
0

我猜下面的编,会像你预期的那样工作,

锁定在 Thread1.Class 上,两个线程不会同时执行该方法

public class Test {
    public static void main(String [] args) { 
        Thread1 t1 = new Thread1();
        Thread1 t2 = new Thread1();
        t1.start();
        t2.start();
    }
}

class Thread1 extends Thread{
    public void run(){
        getNextAvailableVm();
    }
    public void getNextAvailableVm() {
        synchronized(Thread1.class) {
            System.out.println(Thread.currentThread().getName());
            try {
                Thread.sleep(1000);
                }catch(Exception exc){}
            System.out.println(Thread.currentThread().getName());
        }

    }
}

输出 线程 1 线程 1 线程 0 线程 0

于 2013-09-09T11:00:12.810 回答