最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java?多線程并發(fā)LockSupport

 更新時(shí)間:2022年06月16日 08:34:56   作者:??自動(dòng)化BUG制造器????  
這篇文章主要介紹了Java?多線程并發(fā)LockSupport,LockSupport?類(lèi)是用于創(chuàng)建鎖和其他同步類(lèi)的基本線程阻塞原語(yǔ),更多相關(guān)內(nèi)容需要得小伙伴可以參考一下下面文章內(nèi)容

概覽

這部分內(nèi)容來(lái)自于這個(gè)類(lèi)的注釋?zhuān)?jiǎn)單翻譯了下。

LockSupport 類(lèi)是用于創(chuàng)建鎖和其他同步類(lèi)的基本線程阻塞原語(yǔ)。

它的實(shí)現(xiàn)思想是給每個(gè)使用它的線程頒發(fā)一個(gè)許可,當(dāng)許可是可用狀態(tài)時(shí)(線程有許可),調(diào)用 park 方法會(huì)消耗一個(gè)許可,方法立即返回(與信號(hào)量的作用類(lèi)似),線程可以繼續(xù)執(zhí)行 park 方法后面的邏輯;如果調(diào)用 park 方法前,許可處于不可用狀態(tài)(線程沒(méi)有許可),park 方法不會(huì)立即返回,從而導(dǎo)致線程阻塞。而此時(shí),可以通過(guò)調(diào)用 unpark 方法使許可恢復(fù)到可用狀態(tài)(但與信號(hào)量不同,許可不會(huì)累積。最多有一個(gè))。

方法 park 和 unpark 提供了阻塞和解除阻塞線程的有效方法,這些線程不會(huì)遇到 Thread.suspend 和 Thread.resume 存在的問(wèn)題(因suspend 容易導(dǎo)致死鎖,這倆個(gè)方法因?yàn)檫@個(gè)原因已經(jīng)被棄用 ),因?yàn)?park 和 unpark 調(diào)用的線程,不存在鎖競(jìng)爭(zhēng)。

而如果調(diào)用 park 方法的線程被中斷,park 方法將會(huì)立即 return ,并且有設(shè)置超時(shí)版本的 park 方法。park 方法也可以在任何其他時(shí)間沒(méi)有原因的 return,因此通常必須在返回時(shí)重新檢查條件的循環(huán)中調(diào)用。從這個(gè)意義上說(shuō),park 是對(duì)“繁忙等待”的優(yōu)化,它不會(huì)浪費(fèi)太多時(shí)間旋轉(zhuǎn),但必須與 unpark 配對(duì)才能有效。

park 方法有對(duì)應(yīng)帶有 blocker 對(duì)象參數(shù)的重載方法, blocker 對(duì)象在線程被阻塞時(shí)被記錄,以允許監(jiān)視和診斷工具識(shí)別線程被阻塞的原因。 (此類(lèi)工具可以使用 getBlocker(Thread) 方法訪問(wèn)阻止程序。)強(qiáng)烈建議使用這些表單而不是沒(méi)有此參數(shù)的原始表單。 在鎖實(shí)現(xiàn)中作為阻塞器提供的正常參數(shù)是 this。

本質(zhì)上 LockSupport 實(shí)現(xiàn)了一種自旋,構(gòu)造類(lèi)似于:

while (!canProceed()) { ... LockSupport.park(this); }

其中 `canProceed 或在調(diào)用之前的任何其他操作都不會(huì)導(dǎo)致鎖定或阻塞。 因?yàn)槊總€(gè)線程只有一個(gè)許可,所以任何對(duì) park 的中間使用都可能會(huì)干擾其預(yù)期效果。

示例用法。 這是一個(gè)先進(jìn)先出不可重入鎖類(lèi)的草圖:

 class FIFOMutex {
 ? private final AtomicBoolean locked = new AtomicBoolean(false);
 ? private final Queue<Thread> waiters
 ? ? = new ConcurrentLinkedQueue<Thread>();
 ? public void lock() {
 ? ? boolean wasInterrupted = false;
 ? ? Thread current = Thread.currentThread();
 ? ? waiters.add(current);
 ? ? // Block while not first in queue or cannot acquire lock
 ? ? while (waiters.peek() != current ||
 ? ? ? ? ? ?!locked.compareAndSet(false, true)) {
 ? ? ? LockSupport.park(this);
 ? ? ? if (Thread.interrupted()) // ignore interrupts while waiting
 ? ? ? ? wasInterrupted = true;
 ? ? }
 ? ? waiters.remove();
 ? ? if (wasInterrupted) ? ? ? ? ?// reassert interrupt status on exit
 ? ? ? current.interrupt();
 ? }
 ? public void unlock() {
 ? ? locked.set(false);
 ? ? LockSupport.unpark(waiters.peek());
 ? }
 }

源碼分析

整個(gè) LockSupport 類(lèi)的代碼量還算少,去掉注釋僅有 100 行,所有的屬性和方法都是靜態(tài)的,并且備注明確說(shuō)明了 LockSupport 無(wú)法實(shí)例化:

public class LockSupport {
 ? ?private LockSupport() {} // 無(wú)法實(shí)例化
 ? ?// ...
}

LockSupport 中包含了幾個(gè)私有的內(nèi)部靜態(tài)屬性:

public class LockSupport {
    // 通過(guò)內(nèi)部 API 實(shí)現(xiàn) Hotspot
 ? ?private static final Unsafe U = Unsafe.getUnsafe();
 ? ?private static final long PARKBLOCKER= U.objectFieldOffset(Thread.class, "parkBlocker");
 ? ?private static final long TID = U.objectFieldOffset(Thread.class, "tid");
    // ...
}

從這些內(nèi)部私有的靜態(tài)屬性可以看出,最重要的就是 U 了,LockSupport 中的方法,本質(zhì)上也是調(diào)用U 提供的能力。U 在 CAS 與原子類(lèi)中有介紹,是 JDK 中提供的一些非阻塞線程安全的實(shí)現(xiàn)能力的類(lèi),它的大多數(shù)方法都是 native 方法。

靜態(tài)方法

LockSupport 基本上就是個(gè)靜態(tài)工具類(lèi),它的主要能力,集中在它的靜態(tài)方法中。

public class LockSupport {
    public static void unpark(Thread thread)
    public static void park(Object blocker)
    public static void parkNanos(Object blocker, long nanos)
    public static void parkUntil(Object blocker, long deadline)
    public static Object getBlocker(Thread t)
 ? ?public static void setCurrentBlocker(Object blocker)
 ? ?private static void setBlocker(Thread t, Object arg)
    public static void park()
    public static void parkNanos(long nanos)
    public static void parkUntil(long deadline)
 ? ?static final long getThreadId(Thread thread)
}

從方法名就可以看出,主要分為三個(gè):

  • unpark
  • park
  • getBlocker

Blocker

public static Object getBlocker(Thread t) {
 ? ?if (t == null)
 ? ? ? ?throw new NullPointerException();
 ? ?return U.getReferenceOpaque(t, PARKBLOCKER);
}

private static void setBlocker(Thread t, Object arg) {
 ? ?U.putReferenceOpaque(t, PARKBLOCKER, arg);
}
// 在 JDK 14 之前是不存在該方法的, setBlocker 只能從內(nèi)部進(jìn)行
public static void setCurrentBlocker(Object blocker) {
 ? ?U.putReferenceOpaque(Thread.currentThread(), PARKBLOCKER, blocker);
}

setCurrentBlocker 的作用是,設(shè)置當(dāng)前線程調(diào)用 getBlocker 返回的對(duì)象。 在 JDK 14 后暴露這個(gè)方法的用途,是用來(lái)配合park() 的無(wú)參數(shù)版本設(shè)置 Blocker ,它可以實(shí)現(xiàn) park(blocker) 的效果:

 setCurrentBlocker(b);
 park(); 
 setCurrentBlocker(null);

而私有靜態(tài)方法 setBlocker 是在 park 的有參數(shù)方法中封裝使用的。

對(duì)于 blocker 的保存,本質(zhì)是通過(guò) Unsafe 的 putReferenceOpaque 方法保存和 getReferenceOpaque 方法讀取的。

@IntrinsicCandidate
public final void putReferenceOpaque(Object o, long offset, Object x) {
 ? ?putReferenceVolatile(o, offset, x);
}
// 使用 volatile 存儲(chǔ)語(yǔ)義將引用值存儲(chǔ)到給定的 Java 變量中。 否則等同于 putReference(Object, long, Object)
@IntrinsicCandidate
public native void putReferenceVolatile(Object o, long offset, Object x);

@IntrinsicCandidate
public final Object getReferenceOpaque(Object o, long offset) {
 ? ?return getReferenceVolatile(o, offset);
}
// 從給定的 Java 變量中獲取引用值,具有可變加載語(yǔ)義。 否則等同于 getReference(Object, long)
@IntrinsicCandidate
public native Object getReferenceVolatile(Object o, long offset);

在 src/hotspot/share/opto/library_call.cpp 中發(fā)現(xiàn)了 Java 到 native 方法的映射:

case vmIntrinsics::_putReferenceVolatile: return inline_unsafe_access( is_store, T_OBJECT, ? Volatile, false);

native 最終調(diào)用到是老朋友 inline_unsafe_access 。(這里不詳細(xì)展開(kāi)了。。我也沒(méi)搞明白這個(gè)方法,和匯編指令相關(guān))

需要注意的是,最終的都是將對(duì)象設(shè)置為了 volatile 。充分說(shuō)明 LockSupport 也是一套非阻塞同步方案。

而上面提到的 putReference(Object, long, Object)的作用是:將引用值存儲(chǔ)到給定的 Java 變量中。

@IntrinsicCandidate
public native void putReference(Object o, long offset, Object x);

除非存儲(chǔ)的引用 x 為 null 或與字段類(lèi)型匹配,否則結(jié)果是未定義的。 如果引用 o 不為空,則更新該對(duì)象的卡片標(biāo)記或其他存儲(chǔ)屏障(如果 VM 需要它們)。

unpark

public static void unpark(Thread thread) {
    if (thread != null)
        U.unpark(thread);
}

解除調(diào)用 park 的線程的阻塞狀態(tài),或者如果調(diào)用 park 的線程沒(méi)有阻塞,則會(huì)導(dǎo)致后續(xù)調(diào)用 park 不會(huì)造成阻塞。

注意:這個(gè)操作是不安全的,調(diào)用者必須確保線程沒(méi)有被銷(xiāo)毀。

這是什么意思呢?通過(guò)下面這個(gè)例子可以感受到先調(diào)用 unpark 后,指定參數(shù)中的線程參數(shù)對(duì)象調(diào)用 park 不會(huì)造成阻塞:

class LockSupportDemo {
 ? ?fun check() {
 ? ? ? ?val thread1 = Thread {
 ? ? ? ? ? ?Thread.sleep(1000)
 ? ? ? ? ? ?println("thread1 start + ${Date(System.currentTimeMillis())}")
 ? ? ? ? ? ?LockSupport.park()
 ? ? ? ? ? ?println("thread1 end +  ${Date(System.currentTimeMillis())}")
 ? ? ?  }
?
 ? ? ? ?val thread2 = Thread {
 ? ? ? ? ? ?println("thread2 start +  ${Date(System.currentTimeMillis())}")
 ? ? ? ? ? ?LockSupport.unpark(thread1)
 ? ? ? ? ? ?println("thread2 end +  ${Date(System.currentTimeMillis())}")
 ? ? ?  }
 ? ? ? ?thread1.start()
 ? ? ? ?thread2.start()
 ?  }
}

打印日志:

thread2 start +  Fri Jun 03 02:19:34 CST 2022
thread2 end +  Fri Jun 03 02:19:34 CST 2022
thread1 start + Fri Jun 03 02:19:35 CST 2022
thread1 end +  Fri Jun 03 02:19:35 CST 2022

thread2 優(yōu)先執(zhí)行,thread1 在 thread2 開(kāi)始執(zhí)行 1s 后執(zhí)行,thread1 調(diào)用了 LockSupport.park() ,并沒(méi)有造成自身阻塞。

Unsafe 的 unpark 方法

LockSupport.unpark(thread) 內(nèi)部實(shí)際只調(diào)用了 Unsafe#unpark(thread);

public native void unpark(Object thread);
復(fù)制代碼

又是一個(gè) native 方法。在 JDK 中發(fā)現(xiàn) Parker::unpark 的定義在 os_posix.cpp 和 on_windows.cpp 中:

可以看出這個(gè) native 方法,應(yīng)該在不同的平臺(tái)會(huì)有不同的實(shí)現(xiàn)。

park

park 方法有兩組重載方法:

// 不帶 blocker
public static void park()
public static void parkNanos(long nanos)
public static void parkUntil(long deadline)
// 需要 blocker 參數(shù)
public static void park(Object blocker)
public static void parkNanos(Object blocker, long nanos)
public static void parkUntil(Object blocker, long deadline)

不帶 blocker 參數(shù)的分組

沒(méi)有 blocker 參數(shù)的一組本質(zhì)上的邏輯是:

U.park(boolean, long);
復(fù)制代碼

這一點(diǎn)可以從三個(gè)方法中看出:

public static void park() {
    U.park(false, 0L);
}
public static void parkNanos(long nanos) {
 ? ?if (nanos > 0)
 ? ? ? ?U.park(false, nanos);
}
public static void parkUntil(long deadline) {
 ? ?U.park(true, deadline);
}

這三個(gè)方法的區(qū)別是:

park

方法的作用是:除非許可處于可用狀態(tài),否者關(guān)閉當(dāng)前線程的線程調(diào)度的意圖。如果許可可用,則許可被使用掉,并立即返回。否則當(dāng)前線程因?yàn)榫€程調(diào)度的意圖被關(guān)閉而導(dǎo)致阻塞。

直到發(fā)生以下三種情況之一:

其他線程以當(dāng)前線程為目標(biāo)調(diào)用 unpark

其他線程中斷當(dāng)前線程

調(diào)用虛假地 return(即 no reason)

這個(gè)方法不會(huì)報(bào)告是哪一種原因?qū)е碌?return。調(diào)用者應(yīng)該重新檢查導(dǎo)致線程第一次停止的條件。 例如,調(diào)用者還可以確定線程在返回時(shí)的中斷狀態(tài)。

parkNanos

禁用當(dāng)前線程的線程調(diào)度意圖,直到指定的等待時(shí)間,除非許可可用。如果參數(shù) nanos 為 0 或?yàn)樨?fù)數(shù),這個(gè)方法將不會(huì)做任何事情。

parkUntil

禁用當(dāng)前線程的線程調(diào)度意圖,直到指定的最后期限,除非許可可用。參數(shù) deadline 是截止日期——從 Epoch 開(kāi)始等待的絕對(duì)時(shí)間,以毫秒為單位。

需要 blocker 參數(shù)的分組

public static void park(Object blocker) {
 ? ?Thread t = Thread.currentThread();
 ? ?setBlocker(t, blocker);
 ? ?U.park(false, 0L);
 ? ?setBlocker(t, null);
}
public static void parkNanos(Object blocker, long nanos) {
 ? ?if (nanos > 0) {
 ? ? ? ?Thread t = Thread.currentThread();
 ? ? ? ?setBlocker(t, blocker);
 ? ? ? ?U.park(false, nanos);
 ? ? ? ?setBlocker(t, null);
 ?  }
}
public static void parkUntil(Object blocker, long deadline) {
 ? ?Thread t = Thread.currentThread();
 ? ?setBlocker(t, blocker);
 ? ?U.park(true, deadline);
 ? ?setBlocker(t, null);
}

帶有 blocker 參數(shù)的這組函數(shù),它們和對(duì)應(yīng)的不帶參數(shù)的方法意義是一樣的,多了一個(gè)設(shè)置對(duì)象的操作。而這個(gè)對(duì)象 blocker 是負(fù)責(zé)此線程 parking 的同步對(duì)象 。

這組重載方法有共同的邏輯:

  • 獲取當(dāng)前線程對(duì)象。
  • 將 blocker 對(duì)象的引用值存儲(chǔ)到線程對(duì)象中。
  • 調(diào)用 Unsafe 對(duì)象的 park(boolean, long) 方法。
  • 將當(dāng)前線程對(duì)象存儲(chǔ)的引用值設(shè)置為 null 。

讓我困惑的是,這個(gè)存儲(chǔ)引用值操作有什么作用。但是聯(lián)想到線程操作和對(duì)象,驚奇的發(fā)現(xiàn)我們常用的 API Object.wait() 和 Object.notify() ,好像和這個(gè)場(chǎng)景很像,都用到了一個(gè) Object ,也都造成了線程阻塞喚醒。

park/unpark 和 Object 的 wait/notify

public class LockSupportJava {
 ? ?Object obj = new Object();?
 ? ?public static void main(String[] args) {
 ? ? ? ?LockSupportJava lock = new LockSupportJava();
 ? ? ? ?lock.waitAndNotify();
 ?  }
 ? ?void waitAndNotify() {
 ? ? ? ?Thread thread1 = new Thread(() -> {
 ? ? ? ? ? ?synchronized(obj) {
 ? ? ? ? ? ? ? ?try {
 ? ? ? ? ? ? ? ?    System.out.println("thread1 start + " + new Date(System.currentTimeMillis()));
 ? ? ? ? ? ? ? ? ? ?Thread.sleep(1000);
 ? ? ? ? ? ? ? ? ? ?obj.notify();
 ? ? ? ? ? ? ?      System.out.println("thread1 end + " + new Date(System.currentTimeMillis()));
 ? ? ? ? ? ? ?  } catch (InterruptedException e) {
 ? ? ? ? ? ? ? ? ? ?e.printStackTrace();
 ? ? ? ? ? ? ?  }
 ? ? ? ? ?  }
 ? ? ?  });?
 ? ? ? ?Thread thread2 = new Thread(() -> {
 ? ? ? ? ? ?synchronized(obj) {
 ? ? ? ? ? ? ? ?try {
 ? ? ? ? ? ? ? ? ? ?thread1.start();
 ? ? ? ? ? ? ? ? ? ?Thread.sleep(3000);
 ? ? ? ? ? ? ? ? ? ?System.out.println("thread2 start + " + new Date(System.currentTimeMillis()));
 ? ? ? ? ? ? ? ? ? ?obj.wait();
 ? ? ? ? ? ? ? ? ? ?System.out.println("thread2 end + " + new Date(System.currentTimeMillis()));
 ? ? ? ? ? ? ?  } catch (InterruptedException e) {
 ? ? ? ? ? ? ? ? ? ?e.printStackTrace();
 ? ? ? ? ? ? ?  }
 ? ? ? ? ?  }
 ? ? ?  });
 ? ? ? ?thread2.start();
 ?  }
}

這是一個(gè)簡(jiǎn)單的 Demo ,創(chuàng)建了兩個(gè)線程 thread1 和 thread2 。

線程 2 從主線程先執(zhí)行,持有了 obj對(duì)象的鎖,在它的執(zhí)行邏輯中:

  • 先啟動(dòng)線程 1
  • 線程 2 睡眠 3 秒
  • 三秒后打印 start,obj 對(duì)象調(diào)用 wait ,使當(dāng)前線程讓出對(duì)象的鎖,并進(jìn)入阻塞狀態(tài)。

此時(shí),線程 1 可以獲取到 obj 對(duì)象的鎖了,它的執(zhí)行邏輯:

  • 線程 1 開(kāi)始打印 start
  • 睡眠 1 秒
  • obj 對(duì)象調(diào)用 notify ,線程 2 開(kāi)始嘗試獲取 obj 的鎖。
  • 打印 end ,執(zhí)行結(jié)束,讓出 obj 的鎖

最后,線程 2 重新獲取到了 obj 的鎖,繼續(xù)執(zhí)行打印 end 。

從打印日志中,驗(yàn)證打印順序:

thread2 start + Fri Jun 03 04:02:17 CST 2022
thread1 start + Fri Jun 03 04:02:17 CST 2022
thread1 end + Fri Jun 03 04:02:18 CST 2022
thread2 end + Fri Jun 03 04:02:18 CST 2022

注意:使用wait/notify實(shí)現(xiàn)同步時(shí),必須先調(diào)用wait,后調(diào)用notify,如果先調(diào)用notify,再調(diào)用wait,會(huì)導(dǎo)致線程一直阻塞。

而如果使用 park / unpark 實(shí)現(xiàn)一個(gè)阻塞喚醒效果:

 ? ?Thread thread;
 ? ?void parkAndUnpark() {
 ? ? ? ?Thread thread2 = new Thread(() -> {
 ? ? ? ? ? ?System.out.println("thread2 start + " + new Date(System.currentTimeMillis()));
 ? ? ? ? ? ?thread.start();
 ? ? ? ? ? ?LockSupport.park(obj);
 ? ? ? ? ? ?System.out.println("Blocker info " + LockSupport.getBlocker(Thread.currentThread()));
 ? ? ? ? ? ?System.out.println("thread2 end + " + new Date(System.currentTimeMillis()));
 ? ? ?  });
 ? ? ? ?// 喚起 thread2
 ? ? ? ?Thread thread1 = new Thread(() -> {
 ? ? ? ? ? ?try {
 ? ? ? ? ? ? ? ?System.out.println("thread1 start + " + new Date(System.currentTimeMillis()));
 ? ? ? ? ? ? ? ?Thread.sleep(3000);
 ? ? ? ? ? ? ? ?System.out.println("Blocker info " + LockSupport.getBlocker(thread2));
 ? ? ? ? ? ? ? ?LockSupport.unpark(thread2);
 ? ? ? ? ? ? ? ?System.out.println("thread1 end + " + new Date(System.currentTimeMillis()));
 ? ? ? ? ?  } catch (InterruptedException e) {
 ? ? ? ? ? ? ? ?e.printStackTrace();
 ? ? ? ? ?  }
 ? ? ?  });
 ? ? ? ?thread = thread1;
 ? ? ? ?thread2.start();
 ?  }

parkAndUnpark() 方法中,先啟動(dòng)了線程 2,線程 2 打印完 start 后就啟動(dòng)了線程 1 。而此時(shí)線程 2 繼續(xù)執(zhí)行:

  • 調(diào)用 park 進(jìn)入阻塞狀態(tài)

在線程 2 執(zhí)行上面兩個(gè)邏輯的同時(shí),線程 1 也在同時(shí)執(zhí)行:

  • 線程 1 啟動(dòng)后先打印 start
  • 線程 1 睡眠 3 秒
  • 檢查線程 2 調(diào)用 park(Object)方法設(shè)置的 Blocker 信息
  • 調(diào)用 LockSupport.unpark(thread2) 解除線程 2 的阻塞
  • 線程 1 打印 end 執(zhí)行結(jié)束

線程 2 在被線程 1 喚醒后,繼續(xù)執(zhí)行打印信息:

  • 打印當(dāng)前線程的 Blocker 信息,為 null
  • 打印 end 執(zhí)行結(jié)束

打印日志:

thread2 start + Fri Jun 03 04:24:32 CST 2022
thread1 start + Fri Jun 03 04:24:32 CST 2022
Blocker info java.lang.Object@7a3acdd9
thread1 end + Fri Jun 03 04:24:35 CST 2022
Blocker info null
thread2 end + Fri Jun 03 04:24:35 CST 2022

注意:先調(diào)用 unpark 后調(diào)用 park 也不會(huì)導(dǎo)致阻塞,更加靈活。

可以發(fā)現(xiàn),blocker 在線程恢復(fù)后變成了 null ,個(gè)人理解它的作用就是用來(lái)做阻塞標(biāo)記的,可以用來(lái)在線程阻塞狀態(tài)下,將一個(gè)對(duì)象設(shè)置上,然后在其他線程中讀取這個(gè)對(duì)象。blocker 與線程的單次阻塞狀態(tài)綁定,可以用于對(duì)線程狀態(tài)的排查和線程狀態(tài)的監(jiān)控。

區(qū)別

從 wait/notify 和 park/unpark 兩種阻塞線程和喚起線程的方式,能夠感受出兩者的不同之處:

  • wait/notify 需要配合 synchronized 進(jìn)行;park/unpark 雖然設(shè)置了 blocker 但全程沒(méi)有鎖。
  • wait/notify 需要保證 wait 在前,notify 在后,否則會(huì)阻塞線程;park/unpark 對(duì)調(diào)用順序沒(méi)有限制。不會(huì)造成阻塞。
  • wait/notify 方法在 Object 中定義,用于對(duì)象鎖的資源讓出;park/unpark 來(lái)自于 LockSupport ,是靜態(tài)方法,用于對(duì)線程本身進(jìn)行掛起喚醒。并可以通過(guò) blocker 綁定線程阻塞狀態(tài)下的一些信息。

個(gè)人感覺(jué) park/unpark 更像是 掛起/恢復(fù),而 Thread.suspend 和 Thread.resume 都已廢棄,是很好的替代方案。

  • suspend,掛起線程,但是不會(huì)釋放類(lèi)似鎖這樣的資源。
  • resume,恢復(fù)線程,如果之前沒(méi)有使用suspend暫停線程,則不起作用。
  • Thread.stop() 由于其固有的風(fēng)險(xiǎn)而被逐步淘汰。當(dāng)你停止一個(gè)線程時(shí),它會(huì)解鎖它鎖定的所有監(jiān)視器。如果以前受這些監(jiān)視器保護(hù)的任何對(duì)象處于不一致?tīng)顟B(tài),其他線程可能會(huì)看到這些對(duì)象處于不一致?tīng)顟B(tài)。 作用在受損物體上的線可能會(huì)有意或無(wú)意地行為不規(guī)律。與其他不受控制的異常不同,ThreadDeath 會(huì)靜默地殺死線程,不會(huì)向用戶發(fā)出程序可能已損壞的警告。損壞發(fā)生后,損壞可能會(huì)在無(wú)法預(yù)料的時(shí)刻出現(xiàn)。此外,在多線程環(huán)境中使用 DBMS – JDBC 時(shí),終止線程會(huì)產(chǎn)生問(wèn)題。
  • Thread.suspend() 已被棄用,因?yàn)樗举|(zhì)上容易死鎖。因此,Thread.resume() 也必須被棄用。當(dāng)目標(biāo)線程被掛起時(shí),它會(huì)在監(jiān)視器上鎖定一個(gè)保護(hù)關(guān)鍵系統(tǒng)資源的鎖,并且在目標(biāo)線程恢復(fù)之前沒(méi)有其他線程可以訪問(wèn)它。如果將重新啟動(dòng)目標(biāo)線程的線程在調(diào)用 resume() 之前嘗試鎖定此監(jiān)視器,則會(huì)發(fā)生死鎖。

到此這篇關(guān)于Java 多線程并發(fā)LockSupport的文章就介紹到這了,更多相關(guān)Java  LockSupport內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java函數(shù)式編程(七):MapReduce

    Java函數(shù)式編程(七):MapReduce

    這篇文章主要介紹了Java函數(shù)式編程(七):MapReduce,本文是系列文章的第7篇,其它文章請(qǐng)參閱本文底部的相關(guān)文章,需要的朋友可以參考下
    2014-09-09
  • Java?+?Selenium?+?OpenCV解決自動(dòng)化測(cè)試中的滑塊驗(yàn)證問(wèn)題

    Java?+?Selenium?+?OpenCV解決自動(dòng)化測(cè)試中的滑塊驗(yàn)證問(wèn)題

    OpenCV是一個(gè)基于Apache2.0許可(開(kāi)源)發(fā)行的跨平臺(tái)計(jì)算機(jī)視覺(jué)和機(jī)器學(xué)習(xí)軟件庫(kù),可以運(yùn)行在Linux、Windows、Android和Mac?OS操作系統(tǒng)上,這篇文章主要介紹了Java?+?Selenium?+?OpenCV解決自動(dòng)化測(cè)試中的滑塊驗(yàn)證,需要的朋友可以參考下
    2022-07-07
  • java實(shí)現(xiàn)解析json復(fù)雜數(shù)據(jù)的第三種思路詳解

    java實(shí)現(xiàn)解析json復(fù)雜數(shù)據(jù)的第三種思路詳解

    這篇文章主要為大家信息介紹了java實(shí)現(xiàn)解析json復(fù)雜數(shù)據(jù)的第三種思路,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2024-01-01
  • SpringBoot?Schedule調(diào)度任務(wù)的動(dòng)態(tài)管理

    SpringBoot?Schedule調(diào)度任務(wù)的動(dòng)態(tài)管理

    Scheduled定時(shí)任務(wù)是Spring?boot自身提供的功能,所以不需要引入Maven依賴包,下面這篇文章主要給大家介紹了關(guān)于SpringBoot通過(guò)@Scheduled實(shí)現(xiàn)定時(shí)任務(wù)以及問(wèn)題解決的相關(guān)資料,需要的朋友可以參考下
    2023-02-02
  • Mybatis Plus 增刪改查的實(shí)現(xiàn)(小白教程)

    Mybatis Plus 增刪改查的實(shí)現(xiàn)(小白教程)

    本文主要介紹了Mybatis Plus 增刪改查,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-09-09
  • Java用split分割含一個(gè)或多個(gè)空格的字符串案例

    Java用split分割含一個(gè)或多個(gè)空格的字符串案例

    這篇文章主要介紹了Java用split分割含一個(gè)或多個(gè)空格的字符串案例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)過(guò)來(lái)看看吧
    2020-09-09
  • Java方法的返回值及注意事項(xiàng)小結(jié)

    Java方法的返回值及注意事項(xiàng)小結(jié)

    這篇文章主要介紹了Java方法的返回值及注意事項(xiàng),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-04-04
  • MyBatis-Plus中如何實(shí)現(xiàn)動(dòng)態(tài)表名

    MyBatis-Plus中如何實(shí)現(xiàn)動(dòng)態(tài)表名

    這篇文章主要介紹了MyBatis-Plus中如何實(shí)現(xiàn)動(dòng)態(tài)表名問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-07-07
  • Java ThreadLocal的設(shè)計(jì)理念與作用

    Java ThreadLocal的設(shè)計(jì)理念與作用

    這篇文章主要介紹了Java ThreadLocal的設(shè)計(jì)理念與作用,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-03-03
  • Java中Spring擴(kuò)展點(diǎn)詳解

    Java中Spring擴(kuò)展點(diǎn)詳解

    這篇文章主要介紹了Java中Spring技巧之?dāng)U展點(diǎn)的應(yīng)用,下文Spring容器的啟動(dòng)流程圖展開(kāi)其內(nèi)容的相關(guān)資料,具有一定的參考價(jià)值,需要的小伙伴可以參考一下
    2022-06-06

最新評(píng)論

永顺县| 安国市| 连州市| 大连市| 苏尼特右旗| 彰武县| 宁安市| 仙居县| 交口县| 天长市| 沭阳县| 茌平县| 诏安县| 淄博市| 翼城县| 西吉县| 仪征市| 乐清市| 故城县| 成安县| 象州县| 永吉县| 怀集县| 石景山区| 绿春县| 涡阳县| 安西县| 周口市| 靖州| 平阴县| 什邡市| 寻甸| 临海市| 饶平县| 古丈县| 龙陵县| 奎屯市| 军事| 海丰县| 丘北县| 志丹县|