0

是的,同步锁定语法很容易,因为它是块结构,但有时你不能使用它。有没有办法显式锁定和解锁对象上的“同步”监视器,以便它与“同步”的先前用法兼容?

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();
 }

当然,在这个例子中,“闭包”会消除这种需要,就像“堆栈范围”的析构函数一样;^>但是......

4

5 回答 5

1

您不能在对象的内在锁上执行此操作,但您可以使用 java.util.concurrent.locks.Lock 代替。

如果你真的需要它,感觉有风险,并且不担心可移植性,你也可以使用 misc.sun.Unsafe,特别是 monitorEnter 和 monitorExit。但是... 可能不是一个好主意。

于 2013-04-09T07:51:38.020 回答
1

您可以使用ReentrantLock

这正是它的作用。

于 2013-04-09T07:53:07.420 回答
1

您可以使用 ReentrantLock 和 Condition 来指示何时可以释放锁。

于 2013-04-09T07:53:10.323 回答
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抛出可能会导致解锁而没有成功匹配锁。

于 2013-04-09T08:08:18.867 回答
0

Java 有一个单独的锁定框架,可以在java.util.concurrent.locksJava 1.5 之后的包中找到。它提供了比synchronized.

class X {
    private final ReentrantLock lock = new ReentrantLock();

    public void m() {
      lock.lock();  // block until condition holds
      try {
        // ... method body
      } finally {
        lock.unlock()
      }
    }
}
于 2013-04-09T07:57:45.637 回答