Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 两个线程如何同时进入同步块?_Java_Multithreading_Synchronized - Fatal编程技术网

Java 两个线程如何同时进入同步块?

Java 两个线程如何同时进入同步块?,java,multithreading,synchronized,Java,Multithreading,Synchronized,发生了一些奇怪的事情。当我进入synchronized块时,我尝试打印线程的名称。在print语句之后,我进行100000秒的husge暂停 @Override public int getNextAvailableVm() { synchronized(this) { System.out.println(Thread.currentThread().getName()); try {Thread.sleep(100000000);}catch(Ex

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

@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);
        .
        .
        .
   }
}
但在运行此方法时,将打印两个线程的名称

Thread-11
Thread-13

在这之后,长时间的停顿发生了。为什么呢?当第一个线程尚未离开同步块时,两个线程如何才能进入同步块?

如果两个线程针对同一对象运行,则不应发生这种情况

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


如果您确实需要多个对象,那么您应该使用
同步(this)
,您应该创建一个
静态最终对象
同步
。请不要在
this.getClass()
上同步,因为它会中断。

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

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

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

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

我想下面的程序会像您预期的那样工作

锁定在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
Thread-0

您确定正在同一对象上调用
getNextAvailableVm()
吗?您确定睡眠没有中断吗?(打印异常块中的内容)@njzk2无法从异常中打印任何内容block@SuhailGupta:可能是因为没有打印声明?@rocketboy comment可能是您的问题。如果在同一对象上正确同步,则没有理由让多个线程访问此块。请不要在
getClass()
上同步。如果开始包含子类,则会中断。如何在此.getClass()上进行同步中断?在ClassName.class上同步也是如此吗?@jenschauder-如果在
this.getClass
上同步,则当任何对象同步时,此类型的所有对象都将被阻止。此外,对象的子类也将无法与超类的对象正确同步。这几乎肯定不是你想要的。