public void method(Type1 inst1, Type2 inst2) {
synchronized(inst1) {
synchronized(inst2) {
//do something now
}
}
}
我可以从这段代码中理解,一旦一个线程进入该方法,它就获得了对inst1的锁定,然后它获取了对inst2的锁定,而没有释放inst1锁定。我假设这两个对象都没有被其他线程锁定。
答案 0 :(得分:4)
1。如果一个线程一次只能锁定一个对象,并且当当前对象的锁定被释放时只能拥有另一个锁,那么这段代码怎么能有效,或者更确切地说,它是一个有效的代码,我认为我已经看到了某处?
这是一个有效的代码,锁不在方法所在的对象上,而是在inst1
和inst2
上。此外,锁定不在类上,而是在每个对象上
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(){....}