是同步锁定synmtax很容易,因为它的块结构,但有时你不能使用它。有没有办法明确锁定和解锁对象上的“同步”监视器,以便它与“同步”的先前用法兼容?
class MyObj {
Object locker_ = new Object();
void lockedMethod() {
synchronized(locker_) {
....
}
}
Iterator lockTraversal() {
explicitlyWaitForAndAcquireLock(locker_); // assume will not throw exception
return(getAnIterator());
}
void unlockTraversal() {
explicitlyReleaselock(locker_);
}
}
MyObj obj = (...)
try {
Iterator it = obj.lockTraversal();
for(;;) // iterate
} finally {
obj.unlockTraversal();
}
当然,在这个例子中,“闭包”将消除这种需要,就像“堆栈范围”的析构函数一样; ^>但是......
答案 0 :(得分:1)
您无法在对象的内部锁上执行此操作,但您可以使用java.util.concurrent.locks.Lock。
如果你确实需要它,感觉有风险,并且不担心可移植性,你也可以使用misc.sun.Unsafe,特别是monitorEnter和monitorExit。但是......可能不是一个好主意。
答案 1 :(得分:1)
您可以使用ReentrantLock。
这正是它的作用。
答案 2 :(得分:1)
您可以使用ReentrantLock和Condition来指示何时可以释放锁定。
答案 3 :(得分:1)
JVM验证程序的设计使锁定和解锁必须平衡。因此,您不能明确地使用未配对的锁定和解锁。
你可以把锁保存在另一个线程中,只要你不依赖于可重入行为(这对我来说似乎总是一个坏主意)。以线程安全的方式与其他线程通信将确保您获得相关的发生之前的关系。
实现目标的标准方法是Execute Around idiom,javax.swing.text.AbstractDocument.render使用。
在Java SE 7及更早版本(不是1.0 *)中,Execute Around看起来像:
public interface Traversal<T>() {
void traverse(Iterator<T> iter);
}
public class MyObj {
private final Object lock = new Object();
...
public void lockTraversal(Traversal<String> block) {
synchronized (lock) {
block.traverse(getAnIterator());
}
}
}
MyObj obj = (...)
obj.lockTraversal(new Traversal<String>() {
public void traverse(Iterator<String> iter) {
...
}
});
从Java SE 8开始,除了你可以写下以下内容之外,它们大致相同:
obj.lockTraversal({iter -> // Guess type of iter.
...
});
正如其他人所提到的,java.util.concurrent.locks
提供的锁具有更少的约束。请注意,丢失这些约束可能会导致细微的错误。例如,在原始问题中lockTraveral
投掷可能导致解锁而没有成功的匹配锁定。
答案 4 :(得分:0)
Java有一个单独的锁定框架,可以在Java 1.5之后的java.util.concurrent.locks
包中找到。它提供了比synchronized
更广泛的选项。
class X {
private final ReentrantLock lock = new ReentrantLock();
public void m() {
lock.lock(); // block until condition holds
try {
// ... method body
} finally {
lock.unlock()
}
}
}