自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

多線程核心要點(diǎn),你知道嗎?

開發(fā) 前端
在 JDK 1.6 引入了兩種新型鎖機(jī)制:偏向鎖和輕量級(jí)鎖,它們的引入是為了解決在沒有多線程競(jìng)爭(zhēng)或基本沒有競(jìng)爭(zhēng)的場(chǎng)景下因使用傳統(tǒng)鎖機(jī)制帶來(lái)的性能開銷問(wèn)題。

多線程

線程的狀態(tài)。

一、線程池

  1. 提交任務(wù)時(shí) 4 種情況:
  • 小于 corePoolSize addWorker()。
  • 大于 corePoolSize workQueue.offer(command) 直接增加 task 如果增加失敗就拒絕。

  1. 拒絕策略
  • AbortPolicy 拋出異常,默認(rèn)。
  • CallerRunsPolicy 不使用線程池執(zhí)行。
  • DiscardPolicy 直接丟棄。
  • DiscardOldestPolicy 丟棄隊(duì)列中最舊的任務(wù)。

二、鎖

Sychronized 原理

用法:

  • 方法
  • 代碼塊

在 JDK 1.6 之前,synchronized 只有傳統(tǒng)的鎖機(jī)制,因此給開發(fā)者留下了 synchronized 關(guān)鍵字相比于其他同步機(jī)制性能不好的印象。在 JDK 1.6 引入了兩種新型鎖機(jī)制:偏向鎖和輕量級(jí)鎖,它們的引入是為了解決在沒有多線程競(jìng)爭(zhēng)或基本沒有競(jìng)爭(zhēng)的場(chǎng)景下因使用傳統(tǒng)鎖機(jī)制帶來(lái)的性能開銷問(wèn)題。

鎖的升級(jí): 偏向鎖->輕量級(jí)鎖->重量鎖

鎖的映射關(guān)系存在對(duì)象頭中的。32 位系統(tǒng)上各狀態(tài)如圖所示:

偏向鎖:

當(dāng) JVM 啟用了偏向鎖,那么新創(chuàng)建的對(duì)象都是可偏向狀態(tài),此時(shí) mark word 里的 thread id 為 0,表示未偏向任何線程

加鎖過(guò)程:

  1. 當(dāng)對(duì)象第一次被線程獲取鎖時(shí),發(fā)現(xiàn)是未偏向的,那就將 thread id 改為當(dāng)前線程 id,成功繼續(xù)執(zhí)行同步塊中的代碼,失敗則升級(jí)為輕量級(jí)鎖
  2. 當(dāng)被偏向的線程再次進(jìn)入同步塊時(shí),發(fā)現(xiàn)鎖偏向的就是當(dāng)前線程,通過(guò)一些額外檢查后就繼續(xù)執(zhí)行。
  3. 當(dāng)其他線程進(jìn)入同步塊,發(fā)現(xiàn)有偏向的線程了,會(huì)進(jìn)入撤銷偏向鎖邏輯。

解鎖過(guò)程:

  1. 棧中的最近一條 lock record 的 obj 字段設(shè)置為 null

輕量級(jí)鎖:

線程在執(zhí)行同步塊之前,JVM 會(huì)在線程的棧幀上建立一個(gè) Lock Record。其包括了一個(gè)存儲(chǔ)對(duì)象頭中的 mark word 的 Displaced Mark Word 以及一個(gè)對(duì)象頭指針。

加鎖過(guò)程:

  1. 在線程棧中創(chuàng)建一個(gè) Lock Record,將其 obj refercence 字段指向鎖對(duì)象。
  2. 通過(guò) CAS 指令將 Lock Record 地址放在對(duì)象頭的 mark word 中,如果對(duì)象是無(wú)鎖狀態(tài)則修改成功,代表獲取到了輕量級(jí)鎖。如果失敗進(jìn)入步驟 3
  3. 如果線程以及持有該鎖了,代表這是鎖重入,設(shè)置 Lock Record 第一部分(Displaced Mark Word)為 null,起到了一個(gè)重入計(jì)數(shù)器的作用。然后結(jié)束
  4. 走到這一步說(shuō)明發(fā)生了競(jìng)爭(zhēng),膨脹為重量鎖。

解鎖過(guò)程:

  1. 遍歷線程棧,找到所有 obj 字段等于當(dāng)前鎖對(duì)象的 Lock Record
  2. 如果 Lock Record 的 Displaced Mark Word 為 null,代表是一次重入,將 obj 設(shè)為 null 后 continue
  3. 如果 Lock Record 的 Displaced Mark Word 不為 null,則利用 CAS 指令將對(duì)象頭的 mark word 恢復(fù)成為 Displaced Mark Word。如果成功,則 continue,否則膨脹為重量級(jí)鎖

重量級(jí)鎖:

利用的是 JVM 的監(jiān)視器(Monitor)

java 會(huì)為每個(gè) object 對(duì)象分配一個(gè) monitor,當(dāng)某個(gè)對(duì)象的同步方法(synchronized methods )被多個(gè)線程調(diào)用時(shí),該對(duì)象的 monitor 將負(fù)責(zé)處理這些訪問(wèn)的并發(fā)獨(dú)占要求。

  1. 當(dāng) Sychronized 修飾在代碼塊上的時(shí)候,使用的是 monitorenter 指令和 monitorexit 指令。

monitorenter

過(guò)程如下:

  • 如果 Monitor 的進(jìn)入數(shù)為 0,則該線程進(jìn)入 Monitor,然后進(jìn)入數(shù)+1,然后該線程即為 Monitor 的所有者
  • 如果線程已經(jīng)占有了 Monitor 只是重新進(jìn)入,則進(jìn)入數(shù)+1
  • 如果其他線程占有了,則線程阻塞,直到 Monitor 的進(jìn)入數(shù)為 0,在嘗試獲取

monitorexit

過(guò)程如下:

  • 指令執(zhí)行時(shí),Monitor 的進(jìn)入數(shù)減一,如果進(jìn)入數(shù)為 0,則線程退出 Monitor
  • 其他被阻塞的線程可以嘗試獲取這個(gè) Monitor 的所有權(quán)
  1. Synchronize 作用在方式里時(shí),會(huì)加上一個(gè) ACC_SYNCHRONIZED 標(biāo)識(shí)。當(dāng)有這個(gè)標(biāo)識(shí)后,線程執(zhí)行將先獲取 Monitor,獲取成功才能執(zhí)行方法體。

三、AQS

// acquire方法獲取資源占有權(quán)
public final void acquire(int arg) {
/** 嘗試獲取,tryAcquire方法是子類必須實(shí)現(xiàn)的方法,
* 比如公平鎖和非公平鎖的不同就在于tryAcquire方法的實(shí)現(xiàn)的不同。
* 獲取失敗,則addWaiter方法,包裝node節(jié)點(diǎn),放入node雙向鏈表。再acquireQueued堵塞線程,循環(huán)獲取資源占有權(quán)。
*/
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
protected boolean tryAcquire(int arg) {
throw new UnsupportedOperationException();
}
private Node addWaiter(Node mode) {
//新構(gòu)建的node節(jié)點(diǎn),waitStatus初始值為0
Node node = new Node(Thread.currentThread(), mode);
//Try the fast path of enq; backup to full enq on failure
Node pred = tail;
//如果尾部不為空,則說(shuō)明node雙向鏈表之前已經(jīng)被初始化了,那么直接把新node節(jié)點(diǎn)加入尾部
if (pred != null) {
node.prev = pred;
if (compareAndSetTail(pred, node)) {
pred.next = node;
return node;
}
}
//如果尾部為null,則說(shuō)明node雙向鏈表之前沒有被初始化,則,調(diào)用enq方法,初始化node雙向鏈表,并且把新節(jié)點(diǎn)加入尾部
enq(node);
return node;
}

acquire 方法總結(jié):

如果獲取成功:則 state 加 1,并調(diào)用 AQS 的父類
AbstractOwnableSynchronizer 的設(shè)置獨(dú)占線程,把當(dāng)前獨(dú)占線程設(shè)置當(dāng)前線程。
如果調(diào)用失?。簞t說(shuō)明,前面已經(jīng)有線程占用了這個(gè)資源,需要等待的線程釋放。則把當(dāng)前線程封裝成 node 節(jié)點(diǎn),放入 node 雙向鏈表,之后 Locksupport.pack()堵塞當(dāng)前線程。假如這個(gè)線程堵塞后被喚醒,則繼續(xù)循環(huán)調(diào)用 tryAcquire 方法獲取資源許可,獲取到了,則把自身 node 節(jié)點(diǎn)設(shè)置為 node 鏈表的頭節(jié)點(diǎn),把之前的頭節(jié)點(diǎn)去掉。
node 節(jié)點(diǎn)的 waitStatus 為 signal,則意味這其 next 節(jié)點(diǎn)可以被喚醒。

release 方法總結(jié):

如果線程釋放資源,調(diào)用 release 方法,release 方法會(huì)調(diào)用 tryRelease 方法嘗試釋放資源,如果釋放成功,tryRelease 方法會(huì)將 state 減 1,再調(diào)用 AQS 的父類
AbstractOwnableSynchronizer 的設(shè)置獨(dú)占線程為 null,再 locksupport.unpack()雙向 node 鏈表的頭 node 節(jié)點(diǎn)的線程,恢復(fù)其執(zhí)行。

四、實(shí)戰(zhàn)

順序打印 ABC。

/**
* @description:
* @author: mmc
* @create: 2020-01-03 09:42
**/
public class ThreadABC {
private static Object A = new Object();
private static Object B = new Object();
private static Object C = new Object();
private static class ThreadPrint extends Thread{
private String name;
private Object prev;
private Object self;
public ThreadPrint(String name,Object prev,Object self){
this.name=name;
this.prev=prev;
this.self=self;
}
@Override
public void run() {
for (int i = 0; i < 10; i++) {
synchronized (prev) {
synchronized (self) {
System.out.println(name);
self.notifyAll();
}
try {
if(i>=9){
prev.notifyAll();
}else {
prev.wait();
}

} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
public static void main(String[] args) throws InterruptedException {
ThreadPrint threadA = new ThreadPrint("A",C,A);
ThreadPrint threadB = new ThreadPrint("B",A,B);
ThreadPrint threadC = new ThreadPrint("C",B,C);
threadA.start();
Thread.sleep(10);
threadB.start();
Thread.sleep(10);
threadC.start();
}
}


責(zé)任編輯:姜華 來(lái)源: 今日頭條
相關(guān)推薦

2024-07-08 00:00:01

多線程ThreadC#

2024-10-10 16:53:53

守護(hù)線程編程

2025-01-16 16:41:00

ObjectConditionJDK

2024-02-05 12:08:07

線程方式管理

2024-07-01 08:40:18

tokio派生線程

2025-02-07 10:14:36

2009-10-22 14:55:06

網(wǎng)絡(luò)綜合布線資料

2011-05-07 11:11:21

LCD拼接

2024-05-28 09:12:10

2024-04-07 00:00:00

ESlint命令變量

2023-12-12 08:41:01

2023-12-20 08:23:53

NIO組件非阻塞

2024-04-30 09:02:48

2023-04-26 10:21:04

2022-02-25 08:13:03

物聯(lián)網(wǎng)IOT

2020-09-28 11:14:57

線程數(shù)據(jù)語(yǔ)言

2021-10-14 06:52:47

算法校驗(yàn)碼結(jié)構(gòu)

2022-11-04 14:16:05

2024-09-18 07:00:00

消息隊(duì)列中間件消息隊(duì)列

2025-02-18 08:11:17

點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)