Heim >Java >javaLernprogramm >Detaillierte Erläuterung der Thread-Blockierungsverwendung der LockSupport-Klasse in der Java-Multithread-Programmierung
LockSupport ist ein grundlegendes Thread-Blockierungsprimitiv, das zum Erstellen von Sperren und anderen Synchronisierungsklassen verwendet wird.
Die Funktionen von park() und unpark() in LockSupport bestehen darin, Threads zu blockieren bzw. Threads zu entsperren, und park() und unpark() stoßen nicht auf Deadlocks, die durch „Thread.suspend und Thread.resume“ verursacht werden können. "Frage.
Da park() und unpark() über Berechtigungen verfügen, bleibt der Wettlauf zwischen dem Thread, der park() aufruft, und einem anderen Thread, der versucht, unpark() aufzurufen, aktiv.
Grundlegende Verwendung
LockSupport ist einem binären Semaphor sehr ähnlich (es steht nur 1 Lizenz zur Nutzung zur Verfügung, der aktuelle Thread erhält die Lizenz und setzt die Ausführung fort, wenn die Lizenz vorhanden ist). wurde belegt, der aktuelle Thread ist blockiert und wartet auf den Erhalt der Erlaubnis.
public static void main(String[] args) { LockSupport.park(); System.out.println("block."); }
Führen Sie diesen Code aus und Sie werden feststellen, dass der Hauptthread immer blockiert ist. Da die Lizenz standardmäßig belegt ist, kann die Lizenz beim Aufrufen von park () nicht abgerufen werden und wechselt daher in den Blockierungsstatus.
Der folgende Code: Geben Sie zuerst die Berechtigung frei, holen Sie dann die Berechtigung ein, und der Hauptthread kann normal beendet werden. Der Erwerb und die Freigabe von LockSupport-Berechtigungen sind im Allgemeinen korrespondierend. Wenn Sie mehrmals entparken, gibt es kein Problem mit nur einem Park. Das Ergebnis ist, dass die Berechtigung verfügbar ist.
public static void main(String[] args) { Thread thread = Thread.currentThread(); LockSupport.unpark(thread);//释放许可 LockSupport.park();// 获取许可 System.out.println("b"); }
LockSupport ist nicht wiedereintrittsfähig. Wenn ein Thread LockSupport .park() zweimal hintereinander aufruft, bleibt der Thread definitiv blockiert.
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"); }
Dieser Code gibt a und b aus, aber nicht c, da der Thread beim zweiten Aufruf von Park die Berechtigung und nicht erhalten kann stirbt.
Werfen wir einen Blick auf die Reaktionsfähigkeit von LockSupport auf Unterbrechungen
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"); }
Der letzte Thread gibt den Thread over.true aus. Dies zeigt, dass der Thread, wenn er durch den Aufruf von Park blockiert wird, auf die Interrupt-Anfrage antworten kann (der Interrupt-Status ist auf true gesetzt), aber keine InterruptedException auslöst.
LockSupport-Funktionsliste
// 返回提供给最近一次尚未解除阻塞的 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-Beispiel
Vergleichen Sie „Beispiel 1“ und „Beispiel 2“ unten kann die Verwendung von LockSupport besser verstehen.
Beispiel 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(); // 唤醒“当前对象上的等待线程” } } } }
Beispiel 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); } } }
Ausführen Ergebnis:
main start ta main block ta wakup others main continue
Erklärung: Der Unterschied zwischen Parken und Warten. Bevor Wait den Thread blockiert, muss er die Synchronisationssperre über die Synchronisierung erhalten.
Ausführlichere Erläuterungen zur Thread-Blockierungsverwendung der LockSupport-Klasse in der Java-Multithread-Programmierung finden Sie auf der chinesischen PHP-Website!