ホームページ  >  記事  >  Java  >  Java マルチスレッド プログラミングにおける LockSupport クラスのスレッド ブロックの使用方法の詳細な説明

Java マルチスレッド プログラミングにおける LockSupport クラスのスレッド ブロックの使用方法の詳細な説明

高洛峰
高洛峰オリジナル
2017-01-05 15:56:401525ブラウズ

LockSupport は、ロックやその他の同期クラスを作成するために使用される基本的なスレッド ブロック プリミティブです。
LockSupport の park() と unpark() の機能は、それぞれスレッドをブロックし、スレッドのブロックを解除することであり、park() と unpark() は「Thread.suspend と Thread.resume によって引き起こされる可能性のあるデッドロック」の問題に遭遇しません。 「。」
park() と unpark() には権限があるため、park() を呼び出すスレッドと unpark() を試行する別のスレッドとの間の競合はアクティブのままになります。

基本的な使用法
LockSupport はバイナリ セマフォに非常に似ています (使用できるライセンスは 1 つだけです)。ライセンスが占有されていない場合、現在のスレッドがライセンスを取得し、ライセンスが既に占有されている場合は、現在のスレッドが実行を継続します。スレッドがブロックされており、許可を待っています。

public static void main(String[] args)
{
   LockSupport.park();
   System.out.println("block.");
}

このコードを実行すると、メインスレッドがブロックされていることがわかります。デフォルトではライセンスが占有されているため、park()呼び出し時にライセンスを取得できず、ブロッキング状態になります。

次のコード: 最初に権限を解放し、次に権限を取得すると、メインスレッドは正常に終了できます。 LockSupport の権限の取得と解放は通常対応していますが、複数回パークを解除した場合、結果的には 1 回のパークだけで問題なくアクセスできます。

public static void main(String[] args)
{
   Thread thread = Thread.currentThread();
   LockSupport.unpark(thread);//释放许可
   LockSupport.park();// 获取许可
   System.out.println("b");
}

LockSupport は再入可能ではありません。スレッドが LockSupport .park() を 2 回連続して呼び出すと、スレッドは確実に永久にブロックされます。

public static void main(String[] args) throws Exception
{
 Thread thread = Thread.currentThread();
  
 LockSupport.unpark(thread);
  
 System.out.println("a");
 LockSupport.park();
 System.out.println("b");
 LockSupport.park();
 System.out.println("c");
}

このコードは a と b を出力しますが、c は出力しません。これは、park が 2 回目に呼び出されたときに、スレッドが許可を取得できず、デッドロックが発生するためです。

LockSupport の割り込みに対する応答性を見てみましょう

public static void t2() throws Exception
{
 Thread t = new Thread(new Runnable()
 {
  private int count = 0;
 
  @Override
  public void run()
  {
   long start = System.currentTimeMillis();
   long end = 0;
 
   while ((end - start) <= 1000)
   {
    count++;
    end = System.currentTimeMillis();
   }
 
   System.out.println("after 1 second.count=" + count);
 
  //等待或许许可
   LockSupport.park();
   System.out.println("thread over." + Thread.currentThread().isInterrupted());
 
  }
 });
 
 t.start();
 
 Thread.sleep(2000);
 
 // 中断线程
 t.interrupt();
 
  
 System.out.println("main over");
}

最後のスレッドは thread over.true を出力します。これは、park の呼び出しによってスレッドがブロックされた場合、スレッドは割り込み要求に応答できる (割り込みステータスが true に設定されている) が、InterruptedException はスローされないことを示しています。

LockSupport 関数リスト

// 返回提供给最近一次尚未解除阻塞的 park 方法调用的 blocker 对象,如果该调用不受阻塞,则返回 null。
static Object getBlocker(Thread t)
// 为了线程调度,禁用当前线程,除非许可可用。
static void park()
// 为了线程调度,在许可可用之前禁用当前线程。
static void park(Object blocker)
// 为了线程调度禁用当前线程,最多等待指定的等待时间,除非许可可用。
static void parkNanos(long nanos)
// 为了线程调度,在许可可用前禁用当前线程,并最多等待指定的等待时间。
static void parkNanos(Object blocker, long nanos)
// 为了线程调度,在指定的时限前禁用当前线程,除非许可可用。
static void parkUntil(long deadline)
// 为了线程调度,在指定的时限前禁用当前线程,除非许可可用。
static void parkUntil(Object blocker, long deadline)
// 如果给定线程的许可尚不可用,则使其可用。
static void unpark(Thread thread)


LockSupport の例
LockSupport の使用法をより明確に理解するには、以下の「例 1」と「例 2」を比較してください。
例 1

public class WaitTest1 {
 
  public static void main(String[] args) {
 
    ThreadA ta = new ThreadA("ta");
 
    synchronized(ta) { // 通过synchronized(ta)获取“对象ta的同步锁”
      try {
        System.out.println(Thread.currentThread().getName()+" start ta");
        ta.start();
 
        System.out.println(Thread.currentThread().getName()+" block");
        // 主线程等待
        ta.wait();
 
        System.out.println(Thread.currentThread().getName()+" continue");
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
    }
  }
 
  static class ThreadA extends Thread{
 
    public ThreadA(String name) {
      super(name);
    }
 
    public void run() {
      synchronized (this) { // 通过synchronized(this)获取“当前对象的同步锁”
        System.out.println(Thread.currentThread().getName()+" wakup others");
        notify();  // 唤醒“当前对象上的等待线程”
      }
    }
  }
}

例 2

import java.util.concurrent.locks.LockSupport;
 
public class LockSupportTest1 {
 
  private static Thread mainThread;
 
  public static void main(String[] args) {
 
    ThreadA ta = new ThreadA("ta");
    // 获取主线程
    mainThread = Thread.currentThread();
 
    System.out.println(Thread.currentThread().getName()+" start ta");
    ta.start();
 
    System.out.println(Thread.currentThread().getName()+" block");
    // 主线程阻塞
    LockSupport.park(mainThread);
 
    System.out.println(Thread.currentThread().getName()+" continue");
  }
 
  static class ThreadA extends Thread{
 
    public ThreadA(String name) {
      super(name);
    }
 
    public void run() {
      System.out.println(Thread.currentThread().getName()+" wakup others");
      // 唤醒“主线程”
      LockSupport.unpark(mainThread);
    }
  }
}

実行結果:

main start ta
main block
ta wakup others
main continue

説明: park と wait の違い。 wait がスレッドをブロックする前に、synchronized を通じて同期ロックを取得する必要があります。


Java マルチスレッド プログラミングにおける LockSupport クラスの使用をブロックするスレッドの詳細については、PHP 中国語 Web サイトの関連記事に注目してください。


声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。