JUCソース分析5-locks-LockSupport

3238 ワード

LockSupportはunsafeを通じてスレッドをブロックし、起動する方法を提供し、AQSや他のlockはこのベースクラスに使用されます.
private LockSupport() {} // Cannot be instantiated.

private static final Unsafe unsafe = Unsafe.getUnsafe();
private static final long parkBlockerOffset;

static {
    try {
        parkBlockerOffset = unsafe.objectFieldOffset
            (java.lang.Thread.class.getDeclaredField("parkBlocker"));
    } catch (Exception ex) { throw new Error(ex); }
}

各スレッドにはvolatile Object parkBlockerがあります.フィールドは、ブロックを設定するときにそのスレッドにブロックされ、スレッドを監視するために使用できます.LockSupportでは、parkBlockerの設定と取得方法も提供されています.
private static void setBlocker(Thread t, Object arg) {
    // Even though volatile, hotspot doesn't need a write barrier here.
    unsafe.putObject(t, parkBlockerOffset, arg);
}
public static Object getBlocker(Thread t) {
    if (t == null)
        throw new NullPointerException();
    return unsafe.getObjectVolatile(t, parkBlockerOffset);
}

LockSupportは、最下位のunsafeを介してpark,unpark操作を提供する.簡単に言えば、下位層は二義性を維持しています.
_counterはライセンスを保存します.このライセンスは使い捨てであることに注意してください.unpark操作は値を1に設定し、park操作は値が1であるかどうかをチェックします.1は直接戻り、1でないとブロックされます.
次の状況を考慮します.
1.unpark->park、unparkは許可を解放し、parkは直接戻り、ブロックしない.
2.unpark->park->park、unparkは1つの許可を解放し、2回のparkブロック;
3.park->unpark->unpark、parkブロック後に何度もunpark、unpark修正_counterは1で、複数回呼び出しても構わないが、なぜこれを単独で提案したのかは、AQS共有モードでロックを取得した後、ロック待ちのスレッドをすべて通知し、ブロックキューからヘッダノードを削除/起動してforループを使用するため、複数回unpark操作が可能であると感じたからである(個人的な考えでは、必ずしも完全に正確ではなく、誰が理解しているか説明できる).
wait/notifyを使用して同期を実現すると、notifyがwaitの前に実行され、waitがブロックされ続け、問題が発生します.
blockerパラメータとblockerパラメータを持たない:
public static void park(Object blocker) {
    Thread t = Thread.currentThread();
    setBlocker(t, blocker);
    unsafe.park(false, 0L);
    setBlocker(t, null);
}

public static void parkNanos(Object blocker, long nanos) {
    if (nanos > 0) {
        Thread t = Thread.currentThread();
        setBlocker(t, blocker);
        unsafe.park(false, nanos);
        setBlocker(t, null);
    }
}

public static void parkUntil(Object blocker, long deadline) {
    Thread t = Thread.currentThread();
    setBlocker(t, blocker);
    unsafe.park(true, deadline);
    setBlocker(t, null);
}

public static void park() {
    unsafe.park(false, 0L);
}

public static void parkNanos(long nanos) {
    if (nanos > 0)
        unsafe.park(false, nanos);
}

public static void parkUntil(long deadline) {
    unsafe.park(true, deadline);
}

LockSupportのjavadoc説明は3の場合すぐに戻ります.
1.他のスレッドが本スレッドのunpark操作を呼び出した.
2.他のスレッドが本スレッドを中断
3.The call spuriously (that is, for no reason) returns.
上記の3つのケースを除いて、下層Unsafeのpublic native void park(boolean flag,long l);次の場合も起動します.
1.flagはtrueで、転送されたdeallineは
2.flagはfalseで、入力したpark時間timeは着きました
unpark操作が起動すると、スレッドスケジューリングは各プラットフォームによって自分で制御されます.
<span style="font-size:18px;">public static void unpark(Thread thread) {
    if (thread != null)
        unsafe.unpark(thread);
}</span>

参照先:
http://blog.csdn.net/hengyunabc/article/details/28126139 
http://www.360doc.com/content/14/0812/22/1073512_401408738.shtml