我想知道是否有一种简单的方法来制作synchronized
锁,以响应不断变化的引用。我有看起来像这样的代码:
private void fus(){
synchronized(someRef){
someRef.roh();
}
}
...
private void dah(){
someRef = someOtherRef;
}
我想发生的是:
fus
,并在调用someref
时获得对roh()
的锁定。假设roh
永不终止。 fus
,开始等待someRef`释放,并停留在那里(目前)。 dah
并修改someRef
。 someRef
不再引用线程A锁定的对象。 实际发生的是:
fus
,并在调用someref
时获得对roh()
的锁定。假设roh
永不终止。 fus
,找到锁,并等待其释放(永远)。 dah
并修改someRef
。 someref
,而是查看A持有的锁。有没有一种方法可以使线程B要么重新检查锁以更改引用,要么将其“弹开”到其他代码中? (类似于sychronizedOrElse吗?)
最佳答案
当然有办法,但是synchronized
却没有。推理:在第二个线程输入fus()
的时间点,第一个线程持有someRef
引用的对象的固有锁定。重要提示:第二个线程仍会在此对象上看到someRef
引用,并将尝试获取此锁。稍后,当第三个线程更改引用someRef
时,它将不得不以某种方式通知第二个线程此事件。 synchronized
是不可能的。
据我所知,没有像synchronized
这样的内置语言功能来处理这种同步。
一种稍微不同的方法是在您的类中管理 Lock
或给someRef
一个Lock
类型的属性。可以使用lock()
或tryLock()
来代替tryLock(long timeout, TimeUnit unit)
。这是关于如何实现此方案的方案(假设someRef
具有Lock
属性):
volatile SomeRef someRef = ... // important: make this volatile to deny caching
...
private void fus(){
while (true) {
SomeRef someRef = this.someRef;
Lock lock = someRef.lock;
boolean unlockNecessary = false;
try {
if (lock.tryLock(10, TimeUnit.MILLISECONDS)) { // I have chonse this arbritrarily
unlockNecessary = true;
someRef.roh();
return; // Job is done -> return. Remember: finally will still be executed.
// Alternatively, break; could be used to exit the loop.
}
} catch (InterruptException e) {
e.printStackTrace();
} finally {
if (unlockNecessary) {
lock.unlock();
}
}
}
}
...
private void dah(){
someRef = someOtherRef;
}
现在,当
someRef
更改时,第二个线程将在下一个周期中看到someRef
的新值,因此,如果没有其他线程获得Lock
,它将尝试在新的Lock
上进行同步并成功。