Java Concurrency principle - Unsafe && LockSupport class and AQS synchronization Design

[Related Items]

(https://github.com/Wasabi1234/Java-Concurrency-Progamming-Tutorial)

1 Unsafe class park and unpark

public native void park(boolean var1, long var2);
public native void unpark(Object var1);
  • The park method used to block a thread, the first parameter is used to indicate parameters behind the absolute time or relative time, true represents an absolute time, false representation from relative time after the start of the moment. The thread blocking call park here.
  • unpark to release blocked a thread, the thread is represented by the parameter var1

for example:

2 LockSupport

Unsafe or directly place the inconvenience, thus providing a secondary lock bag LockSupport class encapsulates park and unpark

for example:

As can be seen, the use of LockSupport than directly only Unsafe more convenient.

Further, LockSupport can also be used to set a thread Blocker objects, threads facilitate commissioning and testing, the principle is to use the method directly Unsafe putObject parkBlocker the Thread object attributes, and reading the Blocker objects at the right time, the following examples:

3 AQS synchronizer

Various lock ReentrantLock, ReentrantReadWriteLock and various synchronizers such Semaphore, CountDownLatch like core are AbstractQueuedSynchronizer

这里有一个非常简单的例子SimpleLock,实现了一个最简单的排它锁。

  • 当有线程获得锁时,其他线程只能等待
  • 当这个线程释放锁时,其他线程可以竞争获取锁


运行结果表明,通过简单的几行代码,就实行了一个锁的所有功能。

根据JUC作者的建议,AQS的使用方法要遵循上面这个模式。

使用一个内部类Sync来继承AQS,并实现AQS的相关方法

一般是

  • tryAcquire
  • tryRelease(排它锁)

或者

  • tryAcquireShared
  • tryReleaseShared(共享锁)

在内部使用代理模式实现锁的功能

这样可以让暴露出的同步、互斥方法名由程序员自行决定。
例如各种锁可以使用

  • lock
  • unlock

Semaphore可以使用

  • acquire
  • release

CountDownLatch可以使用

  • await
  • countDown

2 AQS基本原理

要实现一个同步器,需要三个条件:

  1. 一个同步状态值,且可原子操作该状态值.显然CAS胜任
  2. 阻塞线程和解除阻塞线程的机制,可以用LockSupport来实现
  3. 维护一个阻塞线程的队列,并在队列的每个节点中存储线程的状态等信息

让我们看看AQS又是如何设计满足的这三个条件。

2.1 状态值及相应的操作方法

private volatile int state;

protected final int getState() {
    return state;
}

protected final void setState(int newState) {
    state = newState;
}

protected final boolean compareAndSetState(int expect, int update) {
    // See below for intrinsics setup to support this
    return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
}

state 为 volatile int型,它的CAS方法,提供原子的比较更新操作。

一般,AQS认为

  • state == 0 时,同步器处于释放状态,多线程此时可竞争获取同步器
  • state ≠ 0 时,同步器处于已获取状态,后续线程需进入队列,等待同步器(可重入同步器允许获取同步器的线程再次进入该同步器,此时使用state计数)
  • 当然,很多情况下,程序员也可自己定义state的值的含义,特别是在实现读写锁时,需要将state一分为二的用。

2.2 阻塞和解除阻塞

LockSupport 提供了阻塞和解除阻塞的功能。因此,所有同步器的阻塞操作其实都是基于LockSupport的,也就是基于Unsafe的park和unpark方法的。

2.3 线程等待队列

AQS内部提供了一个Node类型,它是用来形成“线程等待队列”的节点类型,以及一个由Node类型组成的队列。

Guess you like

Origin www.cnblogs.com/JavaEdge/p/12151106.html