硬核干货:5W字17张高清图理解同步器框架AbstractQueuedSynchronizer (13)

AQS是一个抽象的同步器基础框架,其实我们也可以直接使用它实现一些高级的并发框架。下面基于AQS实现一些非内建的功能,这两个例子来自于AQS的注释中。

metux

大学C语言课程中经常提及到的只有一个资源的metux(互斥区),也就是说,同一个时刻,只能有一个线程获取到资源,其他获取资源的线程需要阻塞等待到前一个线程释放资源。

public class Metux implements Lock, Serializable { private static class Sync extends AbstractQueuedSynchronizer { @Override protected boolean tryAcquire(int arg) { assert 1 == arg; if (compareAndSetState(0, 1)) { setExclusiveOwnerThread(Thread.currentThread()); return true; } return false; } @Override protected boolean tryRelease(int arg) { assert 1 == arg; if (!isHeldExclusively()) { throw new IllegalMonitorStateException(); } setExclusiveOwnerThread(null); setState(0); return true; } public Condition newCondition() { return new ConditionObject(); } public boolean isLocked() { return getState() != 0; } @Override public boolean isHeldExclusively() { return getExclusiveOwnerThread() == Thread.currentThread(); } private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException { s.defaultReadObject(); setState(0); } } private final Sync sync = new Sync(); @Override public void lock() { sync.acquire(1); } @Override public void lockInterruptibly() throws InterruptedException { sync.acquireInterruptibly(1); } @Override public boolean tryLock() { return sync.tryAcquire(1); } @Override public boolean tryLock(long time, TimeUnit unit) throws InterruptedException { return sync.tryAcquireNanos(1, unit.toNanos(time)); } public boolean isLocked() { return sync.isLocked(); } public boolean isHeldByCurrentThread() { return sync.isHeldExclusively(); } @Override public void unlock() { sync.release(1); } @Override public Condition newCondition() { return sync.newCondition(); } public static void main(String[] args) throws Exception { final Metux metux = new Metux(); new Thread(() -> { metux.lock(); System.out.println(String.format("%s-thread-1获取锁成功休眠3秒...", LocalDateTime.now())); try { Thread.sleep(3000); } catch (InterruptedException e) { //ignore } metux.unlock(); System.out.println(String.format("%s-thread-1获解锁成功...", LocalDateTime.now())); return; }, "thread-1").start(); new Thread(() -> { metux.lock(); System.out.println(String.format("%s-thread-2获取锁成功...",LocalDateTime.now())); return; }, "thread-2").start(); Thread.sleep(Integer.MAX_VALUE); } }

某个时间的某次运行结果如下:

2019-04-07T11:49:27.858791200-thread-1获取锁成功休眠3秒... 2019-04-07T11:49:30.876567-thread-2获取锁成功... 2019-04-07T11:49:30.876567-thread-1获解锁成功... 二元栅栏

二元栅栏是CountDownLatch的简化版,只允许一个线程阻塞,由另一个线程负责唤醒。

public class BooleanLatch { private static class Sync extends AbstractQueuedSynchronizer { boolean isSignalled() { return getState() != 0; } @Override protected int tryAcquireShared(int ignore) { return isSignalled() ? 1 : -1; } @Override 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); } public static void main(String[] args) throws Exception { BooleanLatch latch = new BooleanLatch(); new Thread(() -> { try { Thread.sleep(3000); } catch (InterruptedException e) { //ignore } latch.signal(); }).start(); System.out.println(String.format("[%s]-主线程进入阻塞...", LocalDateTime.now())); latch.await(); System.out.println(String.format("[%s]-主线程进被唤醒...", LocalDateTime.now())); } }

某个时间的某次运行结果如下:

[2019-04-07T11:55:12.647816200]-主线程进入阻塞... [2019-04-07T11:55:15.632088]-主线程进被唤醒... 小结

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zywszj.html