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

问题描述 投票:2回答:4
public void method(Type1 inst1, Type2 inst2) {
  synchronized(inst1) {
    synchronized(inst2) {
      //do something now
    }
  }
}

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

  1. 如果一个线程一次只能锁定一个对象,并且当当前对象的锁定被释放时只能拥有另一个锁,那么这段代码怎么可能有效,或者更确切地说,它是一个有效的代码,我认为我已经看到了某处?
  2. 如果Type1和Type2相同怎么办?
  3. 如果我们使方法同步,会发生什么情况,考虑到它位于方法的参数类型以外的类中?
java multithreading synchronization thread-synchronization
4个回答
4
投票

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

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

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

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

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

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


1
投票

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


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上的锁定。


0
投票

那个代码肯定会导致死锁雷区。

锁定inst2的第二个线程(threa2)不一定必须通过methodA运行,但可以在另一个过程中锁定对象inst2,并在methodA中的thread1之前执行,然后在释放之前访问方法A并尝试锁定inst2 INST2。 AHHHHH! boooom! :(。

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

public synchronized void method(){....}

© www.soinside.com 2019 - 2024. All rights reserved.