java concurrent 包中的Sync类

先看一个这个类的签名:

package java.util.concurrent.locks

public abstract class AbstractQueuedSynchronizer 
extends java.util.concurrent.locks.AbstractOwnableSynchronizer
implements java.io.Serializable

提供一个阻塞锁和相关同步器(信号量,事件等)框架的实现,基于先进先出(FIFO)等待队列。这个类被设计用来为多种同步器提供基础,这些同步器依赖于一个代表状态的单个原子类型的int值。子类必须定义protected方法来改变这个状态,定义的状态意味着这个对象被获取或者释放。除了这些,这个类其他的方法执行所有的入队(queuing )和阻塞(blocking )机制。子类可以维护其他的状态字段,但是考虑到同步,仅仅使用 getState, setState and compareAndSetState操作int值才会自动更新。

子类应该作为一个非public的内部辅助类被定义,实现它们宿主类的同步属性。类AbstractQueuedSynchronizer 不实现任何同步接口,代之的是定义方法例如acquireInterruptibly , 用来构造锁和相关的同步器去实现它们的公共方法。

这个类支持使用单个默认的互斥模式或者共享模式,也可以同时支持这两种模式。当在一个互斥模式中获取成功,其他线程尝试获取就会失败。共享模式被多个线程获取时可能会(但没必要)成功。这个类不“理解”这些区别,除非在手动操作时,当一个共享模式获取成功时,下一个等待的线程(如果存在这样一个线程)必须还得决定它是否也能获取的到。在不同模式下等待的线程共享同样的FIFO队列。通常,实现类只支持这些模式中的一种,但是在像ReadWriteLock这样的例子中,这些模式可以同时起作用。仅支持互斥模式或者共享模式的子类无需定义某些方法来支持那些用不到的模式。

这个类定义了一个内嵌的AbstractQueuedSynchronizer.ConditionObject 类,它作为一个Condition 的实现,被子类用来支持互斥模式,isHeldExclusively 方法报告同步是否互斥地被当前线程所持有,release方法完全释放对象,acquire返回保存的状态值,最终,恢复当前对象到它之前的状态。

AbstractQueuedSynchronizer 中d方的法创建这样一个condition,如果这个限制不能被满足,不要使用它。AbstractQueuedSynchronizer.ConditionObject 行为依赖于它的同步器语义实现的过程。

这个类为内置的队列提供检查,探测和监视方法,以及为condition 条件对象提供相似的方法。这些可以依照要求,作为一个同步语义的AbstractQueuedSynchronizer 被导出到类中。

这个类的序列化仅存储了基础的原子整型来维护状态,这样,反序列化后的对象含有空的线程队列。典型的要求可序列化的子类会定义一个readObject方法,存储这个到一个已知最初的反序列化后的状态。

使用

要使用这个类作为同步器的基础,重定义如下的方法,如果适用的话,通过检查和/或者修改使用getState, setState 和/或 compareAndSetState来同步状态:

tryAcquire
tryRelease
tryAcquireShared
tryReleaseShared
isHeldExclusively

每一个方法默认抛出一个UnsupportedOperationException异常。这些方法的实现,必须是内部线程安全的,以及必须普遍上是短暂的和非阻塞的。使用这个类的唯一途径是定义这些方法。其他所有的方法被定义为final,因为他们不能被单独变化。

你可能也会找到从AbstractOwnableSynchronizer 继承的方法用来跟踪线程,拥有一个互斥同步器。鼓励你使用他们——这个将启用监控和诊断工具在决定那个线程持有锁的时候为用户提供帮助。

即便这个类是基于内部的FIFO队列,他不自动自动强制FIFO获取策略。互斥同步的核心使用如下的形式:

   Acquire:
       while (!tryAcquire(arg)) {
          enqueue thread if it is not already queued;
          possibly block current thread;
       }

   Release:
       if (tryRelease(arg))
          unblock the first queued thread;

(Shared mode is similar but may involve cascading signals.)
Because checks in acquire are invoked before enqueuing, a newly acquiring thread may barge ahead of others that are blocked and queued. However, you can, if desired, define tryAcquire and/or tryAcquireShared to disable barging by internally invoking one or more of the inspection methods, thereby providing a fair FIFO acquisition order. In particular, most fair synchronizers can define tryAcquire to return false if hasQueuedPredecessors (a method specifically designed to be used by fair synchronizers) returns true. Other variations are possible.

对于默认策略(也叫做成贪婪,弃权和护送避免),吞吐量和可扩展性通常是最高的。然而不保证是公平或者无饥饿的,更早入队的线程被允许在后续在队的线程之前重新竞争,每一次重新竞争有一个公正的机会来赢过到来的线程。而且,acquires 在多数的场景中不“自旋”,他们可能在阻塞之前使用其他计算执行多个tryAcquire的调用。
This gives most of the benefits of spins when exclusive synchronization is only briefly held, without most of the liabilities when it isn’t. If so desired, you can augment this by preceding calls to acquire methods with “fast-path” checks, possibly prechecking hasContended and/or hasQueuedThreads to only do so if the synchronizer is likely not to be contended

这个类通过特殊化它的同步器使用范围,依赖于int型的状态,获取和释放参数,以及一个内置的FIFO等待队列,在某种程度上为同步提供了一个有效和可扩展的基础。当这个不够用的时候,你可以由一个使用原子类的底层次构建一个同步器。你拥有自定义的java.util.Queue 类,和LockSupport 阻塞支持。

使用示例

这里有一个不可重入的互斥锁类,它使用值0代表解锁状态,1代表加锁状态。当一个不可重入锁不严格要求当前属主线程做记录,这个类仍然会做,使得监控变的简单。它还支持条件,暴漏这其中的一个探测方法:

 class Mutex implements Lock, java.io.Serializable {
    // Our internal helper class
    private static class Sync extends AbstractQueuedSynchronizer {
      // Reports whether in locked state
      protected boolean isHeldExclusively() {
        return getState() == 1;
      }

      // Acquires the lock if state is zero
      public boolean tryAcquire(int acquires) {
        assert acquires == 1; // Otherwise unused
        if (compareAndSetState(0, 1)) {
          setExclusiveOwnerThread(Thread.currentThread());
          return true;
        }
        return false;
      }

      // Releases the lock by setting state to zero
      protected boolean tryRelease(int releases) {
        assert releases == 1; // Otherwise unused
        if (getState() == 0) throw new IllegalMonitorStateException();
        setExclusiveOwnerThread(null);
        setState(0);
        return true;
      }

      // Provides a Condition
      Condition newCondition() { return new ConditionObject(); }

      // Deserializes properly
      private void readObject(ObjectInputStream s)
          throws IOException, ClassNotFoundException {
        s.defaultReadObject();
        setState(0); // reset to unlocked state
      }
    }

    // The sync object does all the hard work. We just forward to it.
    private final Sync sync = new Sync();

    public void lock()                { sync.acquire(1); }
    public boolean tryLock()          { return sync.tryAcquire(1); }
    public void unlock()              { sync.release(1); }
    public Condition newCondition()   { return sync.newCondition(); }
    public boolean isLocked()         { return sync.isHeldExclusively(); }
    public boolean hasQueuedThreads() { return sync.hasQueuedThreads(); }
    public void lockInterruptibly() throws InterruptedException {
      sync.acquireInterruptibly(1);
    }
    public boolean tryLock(long timeout, TimeUnit unit)
        throws InterruptedException {
      return sync.tryAcquireNanos(1, unit.toNanos(timeout));
    }
  }

这里是一个类似于CountDownLatch的闭锁类,除了它仅仅要求触发一个单独的信号。因为一个闭锁是非互斥的,它使用共享的acquire和release方法。

   class BooleanLatch {

    private static class Sync extends AbstractQueuedSynchronizer {
      boolean isSignalled() { return getState() != 0; }

      protected int tryAcquireShared(int ignore) {
        return isSignalled() ? 1 : -1;
      }

      protected boolean tryReleaseShared(int ignore) {
        setState(1);
        return true;
      }
    }

    private final Sync sync = new Sync();
    public boolean isSignalled() { return sync.isSignalled(); }
    public void signal()         { sync.releaseShared(1); }
    public void await() throws InterruptedException {
      sync.acquireSharedInterruptibly(1);
    }
  }
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值