[英]How can a thread acquire lock on two objects simultaneously as in this case?
public void method(Type1 inst1, Type2 inst2) {
synchronized(inst1) {
synchronized(inst2) {
//do something now
}
}
}
从这段代码中我可以理解,一旦线程进入方法,它会先获取inst1的锁,然后再获取inst2的锁,而不释放inst1的锁。 我假设这两个对象都没有被其他线程锁定。
1。 如果一个线程一次只能获取一个对象的锁,而当释放当前对象的锁时只能拥有另一个锁,那么这段代码如何有效?或者,我认为这是一个有效的代码吗?某处?
它是一个有效代码时,锁是不是其中该方法所在的对象上,但在inst1
和inst2
。 同样,锁不是在类上,而是在每个对象上
2。 如果Type1和Type2相同怎么办?
同样,锁在对象上,而不在类上。 如果inst1和inst2相同,则该线程只有一个锁,对于同一线程“重新输入”锁是有效的
3。 如果我们考虑到方法位于方法的参数类型之外的其他类中而使该方法同步,会发生什么情况?
然后,您还有另一个锁,这次是在执行方法的对象(不是类)上。
由于@morgano和@Nick霍尔特 ,我明白, 一个线程可以保持在同一时间多个锁 (不同的对象),或相同的对象上多次(使用获得的锁synchronized
是隐含地折返)。
如果您每次需要以相同的顺序锁定这两个对象,则代码没有问题。
例如,如果您有两种方法
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上的锁。
肯定的是,该代码很可能会导致雷区陷入僵局。
锁定inst2的第二个线程(threa2)不一定必须通过方法A运行,而是可以在另一个过程中锁定对象inst2,并且在方法A中的线程1之前执行此操作,然后在释放之前访问方法A并尝试锁定inst2。 INST2。 AHHHHH! boooom! :(。
建议的解决方案:
与methodA同步,而不是在object上同步,因为那样将锁定在methodA()中访问的所有资源,如下所示
公共同步void methodA(){....}
当您在另一个锁中获取一个锁时会发生死锁:
lock OB1 {
lock OB2 { ... }
}
因为人们可能会尝试锁定一对(1,2)
和花药(2,1)
。 可能有更长的链: (1,2)
+ (2,3)
+ (3,1)
。
您需要在锁之间引入顺序以避免死锁: Java 同步:跨帐户对原子地转移资金?
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.