- public interface Sync {
- public void acquire() throws InterruptedException; //获取许可
- public boolean attempt(long msecs) throws InterruptedException; //尝试获取许可
- public void release(); //释放许可
- }
通过使用Sync可以替代Java synchronized关键字,并提供更加灵活的同步控制。当然,并不是说concurrent工具包是和Java synchronized独立的技术,其实concurrent工具包也是在synchronized的基础上搭建的,从下面对Mutex源码的解析即可以看到这一点。synchronized关键字仅在方法内或者代码块内有效,而使用Sync却可以跨越方法甚至通过在对象之间传递,跨越对象进行同步。这是Sync及concurrent工具包比直接使用synchronized更加强大的地方。
注意Sync中的acquire()和attempt()都会抛出InterruptedException,所以使用Sync及其子类时,调用这些方法一定要捕获InterruptedException。而release()方法并不会抛出InterruptedException,这是因为在acquire()和attempt()方法中可能会调用wait()等待其它线程释放锁。而release()在实现上进行了简化,直接释放锁,不管是否真的持有。所以,你可以对一个并没有acquire()的线程调用release()这也不会有什么问题。而由于release()不会抛出InterruptedException,所以我们可以在catch或finally子句中调用release()以保证获得的锁能够被正确释放。比如:
- class X {
- Sync gate;
- // ...
- public void m() {
- try {
- gate.acquire(); // block until condition holds
- try {
- // ... method body
- }
- finally {
- gate.release();
- }
- }
- catch (InterruptedException ex) {
- // ... evasive action
- }
- }
- }
Mutex是一个非重入的互斥锁。Mutex广泛地用在需要跨越方法的before/after类型的同步环境中。下面是Doug Lea的concurrent工具包中的Mutex的实现。
- public class Mutex implements Sync {
- /** The lock status **/
- protected boolean inuse_ = false;
- public void acquire() throws InterruptedException {
- if (Thread.interrupted()) throw new InterruptedException(); //(1)
- synchronized(this) {
- try {
- while (inuse_) wait();
- inuse_ = true;
- }
- catch (InterruptedException ex) { //(2)
- notify();
- throw ex;
- }
- }
- }
- public synchronized void release() {
- inuse_ = false;
- notify();
- }
- public boolean attempt(long msecs) throws InterruptedException {
- if (Thread.interrupted()) throw new InterruptedException();
- synchronized(this