摘要:通過指令重排可以減少流水線停頓提升巨大效率原則程序順序原則一個(gè)線程內(nèi)保證語義的串行性。鎖規(guī)則解鎖必然發(fā)生在隨后的加鎖前。線程的方法先于它的每一個(gè)動(dòng)作。
1. 基本概念
同步(Synchronous)和異步(Asynchronous) 并發(fā)(Conncurrency)和并行(Parallelism) 臨界區(qū) 阻塞(Blocking)與非阻塞(Non-Blocking) 死鎖(Deadlock)、饑餓(Starvation)和活鎖(Livelock)
同步(Synchronous)和異步(Asynchronous)
并發(fā)(Conncurrency)和并行(Parallelism)
臨界區(qū)
臨界區(qū):公共資源或共享數(shù)據(jù),可被多個(gè)線程使用,但每次只能有一個(gè)線程使用,其他線程需等待
阻塞(Blocking)與非阻塞(Non-Blocking)
阻塞:一個(gè)線程占用了臨界區(qū)資源,其他線程就會(huì)在就必須在臨界區(qū)等待,等待會(huì)導(dǎo)致線程掛起,這就是阻塞
非阻塞:沒有一個(gè)線程可以妨礙其他線程執(zhí)行,所有線程都會(huì)不斷嘗試向前
死鎖(Deadlock)、饑餓(Starvation)和活鎖(Livelock)
死鎖:A線程中占用a資源,并且嘗試去獲取b資源,同時(shí)B線程中占用著b資源,并且嘗試去獲取a資源,此時(shí)誰也無法進(jìn)行下去,導(dǎo)致死鎖
饑餓:資源競爭激烈時(shí),某個(gè)線程長時(shí)間無法獲取到資源,產(chǎn)生饑餓
活鎖:兩個(gè)線程競爭同一資源時(shí)相互謙讓,導(dǎo)致兩個(gè)線程一直在謙讓而無法正常工作
阻塞 無饑餓(Starvation-Free) 無障礙(Obstruction-Free) 無鎖(Lock-Free) 無等待(Wait-Free)
阻塞
使用synchronized關(guān)鍵字或重入鎖等時(shí),會(huì)阻塞其他線程獲取臨界區(qū)資源
無饑餓(Starvation-Free)
使用公平鎖時(shí),先到先得,不會(huì)產(chǎn)生饑餓;非公平鎖,由于競爭激烈,或者某些線程優(yōu)先級(jí)高導(dǎo)致低優(yōu)先級(jí)的線程有可能產(chǎn)生饑餓
無障礙(Obstruction-Free)
無障礙是最弱的非阻塞調(diào)度,兩個(gè)線程均可修改臨界區(qū)數(shù)據(jù),一旦檢測到數(shù)據(jù)不安全,即對(duì)自己修改的數(shù)據(jù)進(jìn)行回滾,確保數(shù)據(jù)安全,沖突嚴(yán)重時(shí)所有線程會(huì)不停回滾從而造成系統(tǒng)無法正常工作.
一般會(huì)配合"一致性標(biāo)記"一起使用,操作前讀取一致性標(biāo)記,修改后再次讀取此標(biāo)記,若不一致則表示數(shù)據(jù)不安全
無鎖(Lock-Free)
無鎖的并行都是無障礙的.無鎖的并發(fā)必然有一個(gè)線程能夠在有限步內(nèi)完成操作離開臨界區(qū).一般都會(huì)包含無窮循環(huán),且可能產(chǎn)生饑餓
無等待(Wait-Free)
無等待在無所的基礎(chǔ)上更進(jìn)一步,要求所有線程必須在有限步內(nèi)訪問完臨界區(qū),這樣就不會(huì)引起饑餓問題
讀線程都是無等待的,寫數(shù)據(jù)時(shí),采用RCU(Read Copy Update)策略,先取得原數(shù)據(jù)副本,再修改副本數(shù)據(jù),修改完后在合適的機(jī)會(huì)寫回?cái)?shù)據(jù)
JMM的技術(shù)點(diǎn)圍繞多線程的原子性、可見性和有序性來建立的
原子性(Atomicity)
32位虛擬機(jī)中操作long型變量是非原子性的,可能造成數(shù)據(jù)不安全
public class MultiThreadLong { public volatile static long t=0; public static class ChangeT implements Runnable{ private long to; public ChangeT(long to){ this.to=to; } @Override public void run() { while(true){ MultiThreadLong.t=to; //賦值臨界區(qū)的t Thread.yield(); //讓出資源 } } } public static class ReadT implements Runnable{ @Override public void run() { while(true){ long tmp=MultiThreadLong.t; if(tmp!=111L && tmp!=-999L && tmp!=333L && tmp!=-444L) System.out.println(tmp); //打印非正常值 Thread.yield(); //讓出資源 } } } public static void main(String[] args) { new Thread(new ChangeT(111L)).start(); new Thread(new ChangeT(-999L)).start(); new Thread(new ChangeT(333L)).start(); new Thread(new ChangeT(-444L)).start(); new Thread(new ReadT()).start(); //輸出: //-4294966963 //4294966852 //-4294966963 } }
可見性
可見性是指一個(gè)線程修改某一個(gè)共享變量的值時(shí),其他線程是否能夠立即知道這個(gè)修改
原因:緩存優(yōu)化或者硬件優(yōu)化問題(內(nèi)存讀寫不會(huì)立即觸發(fā),而先進(jìn)入一個(gè)硬件隊(duì)列);指令重排和編輯器的優(yōu)化
有序性
并發(fā)時(shí),程序的執(zhí)行可能出現(xiàn)亂序,給人感覺就是:寫在前面的代碼,會(huì)在后面執(zhí)行
public class OrderExample { int a=0; boolean flag=false; public void writer(){ a=1; flag=true; //這一步不一定在a=1之后 } public void reader(){ if(flag){ int i=a+1; //當(dāng)flag=true時(shí),a不一定為1,也可能未執(zhí)行a=0 } } }
為什么要指令重拍呢? 完全是出于性能考慮,一條指令可以分為以下幾步: .取指IF。 ·譯碼和取寄存器操作數(shù)ID。 ·執(zhí)行或者有效地址計(jì)算EX。 ·存儲(chǔ)器訪問MEM。 ·寫回WB。 通過指令重排可以減少cpu流水線停頓,提升巨大效率 Happen-Before原則: ·程序順序原則:一個(gè)線程內(nèi)保證語義的串行性。 ·volatile規(guī)則:volatile變量的寫先于讀發(fā)生,這保證了volatile變量的可見性。 ·鎖規(guī)則:解鎖(unlock)必然發(fā)生在隨后的加鎖(lock)前。 ·傳遞性:A先于B,B先于C,那么A必然先于C。 .線程的start()方法先于它的每一個(gè)動(dòng)作。 ·線程的所有操作先于線程的終結(jié)(Thread.join())。 ·線程的中斷(interrupt())先于被中斷線程的代碼。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/75926.html
showImg(https://segmentfault.com/img/bVbeIZ4?w=1949&h=1315);
摘要:探究系統(tǒng)登錄驗(yàn)證碼的實(shí)現(xiàn)后端掘金驗(yàn)證碼生成類手把手教程后端博客系統(tǒng)第一章掘金轉(zhuǎn)眼間時(shí)間就從月份到現(xiàn)在的十一月份了。提供了與標(biāo)準(zhǔn)不同的工作方式我的后端書架后端掘金我的后端書架月前本書架主要針對(duì)后端開發(fā)與架構(gòu)。 Spring Boot干貨系列總綱 | 掘金技術(shù)征文 - 掘金原本地址:Spring Boot干貨系列總綱博客地址:http://tengj.top/ 前言 博主16年認(rèn)識(shí)Spin...
摘要:實(shí)戰(zhàn)讀書筆記第一章從方法傳遞到接著上次的,繼續(xù)來了解一下,如果繼續(xù)簡化代碼。去掉并且生成的數(shù)字是萬,所消耗的時(shí)間循序流并行流至于為什么有時(shí)候并行流效率比循序流還低,這個(gè)以后的文章會(huì)解釋。 《Java8實(shí)戰(zhàn)》-讀書筆記第一章(02) 從方法傳遞到Lambda 接著上次的Predicate,繼續(xù)來了解一下,如果繼續(xù)簡化代碼。 把方法作為值來傳遞雖然很有用,但是要是有很多類似與isHeavy...
摘要:無鎖無鎖的并行都是無障礙的,但不同的是無鎖的并發(fā)保證了必然有一個(gè)線程能夠在有限步驟內(nèi)離開臨界區(qū)。有關(guān)并行的兩個(gè)重要定律未完待續(xù)實(shí)戰(zhàn)高并發(fā)程序設(shè)計(jì)第一章走入并行世界讀書筆記歡迎加入咖啡館的春天。 必須知道的幾個(gè)概念 同步(Synchronous)和異步(Asynchronous) 同步方法調(diào)用一旦開始,調(diào)用者必須等待方法調(diào)用返回后才能繼續(xù)后續(xù)行為。異步方法調(diào)用更像一個(gè)消息傳遞,一旦開始就...
閱讀 1277·2021-09-23 11:51
閱讀 1397·2021-09-04 16:45
閱讀 636·2019-08-30 15:54
閱讀 2088·2019-08-30 15:52
閱讀 1607·2019-08-30 11:17
閱讀 3110·2019-08-29 13:59
閱讀 2025·2019-08-28 18:09
閱讀 391·2019-08-26 12:15