Maison >Java >javaDidacticiel >Explication détaillée de l'utilisation du blocage des threads de la classe LockSupport dans la programmation multithread Java

Explication détaillée de l'utilisation du blocage des threads de la classe LockSupport dans la programmation multithread Java

高洛峰
高洛峰original
2017-01-05 15:56:401561parcourir

LockSupport est une primitive de blocage de thread de base utilisée pour créer des verrous et d'autres classes de synchronisation.
Les fonctions de park() et unpark() dans LockSupport sont respectivement de bloquer et de débloquer les threads, et park() et unpark() ne rencontreront pas de blocages pouvant être causés par "Thread.suspend et Thread.resume". "question.
Parce que park() et unpark() ont des autorisations ; la course entre le thread appelant park() et un autre thread essayant de unpark() restera active.

Utilisation de base
LockSupport est très similaire à un sémaphore binaire (une seule licence est disponible pour l'utilisation Si la licence n'a pas été occupée, le thread actuel obtient la licence et continue l'exécution si la licence est disponible). a été occupé, le thread actuel est bloqué, en attente d'obtenir l'autorisation.

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

Exécutez ce code et vous constaterez que le fil de discussion principal est toujours bloqué. Étant donné que la licence est occupée par défaut, la licence ne peut pas être obtenue lors de l'appel de park(), elle entre donc dans l'état de blocage.

Le code suivant : libérez d'abord l'autorisation, puis obtenez l'autorisation, et le thread principal peut se terminer normalement. L'acquisition et la libération des autorisations LockSupport correspondent généralement. Si vous déparkez plusieurs fois, il n'y aura aucun problème avec un seul parcage. Le résultat est que l'autorisation est disponible.

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

LockSupport n'est pas réentrant Si un thread appelle LockSupport .park() deux fois de suite, le thread restera définitivement bloqué.

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");
}

Ce code imprime a et b, mais pas c, car lorsque park est appelé pour la deuxième fois, le thread ne peut pas obtenir l'autorisation et meurt.

Jetons un coup d'œil à la réactivité de LockSupport aux interruptions

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");
}

Le fil de discussion final imprimera le fil de discussion over.true. Cela montre que si le thread est bloqué en appelant park, il peut répondre à la demande d'interruption (l'état de l'interruption est défini sur true), mais il ne lancera pas InterruptedException.

Liste des fonctions 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)


Exemple de LockSupport
Comparez « Exemple 1 » et « Exemple 2 » ci-dessous. peut comprendre plus clairement l’utilisation de LockSupport.
Exemple 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();  // 唤醒“当前对象上的等待线程”
      }
    }
  }
}

Exemple 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);
    }
  }
}

Exécuter Résultat :

main start ta
main block
ta wakup others
main continue

Explication : La différence entre se garer et attendre. Avant que l'attente bloque le thread, celui-ci doit obtenir le verrou de synchronisation via synchronisé.


Pour des explications plus détaillées sur l'utilisation du blocage de thread de la classe LockSupport dans la programmation multithread Java, veuillez prêter attention au site Web PHP chinois !


Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn