在这种情况下,线程如何同时获取两个对象的锁定?

时间:2014-04-22 10:40:40

标签: java multithreading synchronization thread-synchronization

public void method(Type1 inst1, Type2 inst2) {
  synchronized(inst1) {
    synchronized(inst2) {
      //do something now
    }
  }
}

我可以从这段代码中理解,一旦一个线程进入该方法,它就获得了对inst1的锁定,然后它获取了对inst2的锁定,而没有释放inst1锁定。我假设这两个对象都没有被其他线程锁定。

  1. 如果一个线程只能同时获取一个对象的锁定而且只能 如何锁定当前对象时拥有另一个锁 这段代码可以有效,或者更确切地说,它是一个有效的代码,我认为我已经在某处看到过了吗?
  2. 如果Type1和Type2相同怎么办?
  3. 如果我们让方法同步,会发生什么,考虑到它存在于 除了方法的参数类型之外的类?

4 个答案:

答案 0 :(得分:4)

  

1。如果一个线程一次只能锁定一个对象,并且当当前对象的锁定被释放时只能拥有另一个锁,那么这段代码怎么能有效,或者更确切地说,它是一个有效的代码,我认为我已经看到了某处?

这是一个有效的代码,锁不在方法所在的对象上,而是在inst1inst2上。此外,锁定不在类上,而是在每个对象上

  

2。如果Type1和Type2相同怎么办?

再次,锁在对象上,而不在类上。如果inst1和inst2是相同的,那么线程只有一个锁,它对同一个线程有效,重新输入"锁

  

3。如果我们使方法同步,会发生什么?考虑到它位于方法的参数类型以外的类中?

然后你还有另一个锁,这次是在执行方法的对象(不是类)上。

答案 1 :(得分:1)

感谢 @morgano @Nick Holt ,我明白一个线程可以同时拥有多个锁(不同的对象) ,或多次在同一个对象上(使用synchronized获得的锁是隐式重入的。)

答案 2 :(得分:0)

如果您需要以相同的顺序对这两个对象进行锁定,则代码没有问题。

例如,如果您有两种方法

public void methodA(Type1 inst1, Type2 inst2) {
  synchronized(inst1) {
    synchronized(inst2) {
      //do something now
    }
  }
}

public void methodB(Type1 inst1, Type2 inst2) {
  //wrong
  synchronized(inst2) {
    synchronized(inst1) {
      //do something now
    }
  }
}

你有一个潜在的死锁问题,因为一个线程可以在inst1上获得锁定并等待inst2的锁定,而另一个线程在inst2上锁定并在inst1上等待锁定。

答案 3 :(得分:0)

该代码很可能会导致雷区陷入僵局。

锁定inst2的第二个线程(threa2)不一定必须通过methodA运行,而是可以在另一个过程中锁定对象inst2,并且在methodA中的线程1之前这样做,然后访问方法A并尝试锁定inst2 ,然后释放inst2。啊!嘘! :(。

建议的解决方案:
在methodA而非对象上同步,因为这将锁定在methodA()中访问的所有资源 像这样

公共同步void methodA(){....}