一甜癞、進程和線程
1夕晓、進程
a、擁有自包含的執(zhí)行環(huán)境
b带欢、擁有完整的运授、私有的運行時資源的集合
c、擁有自己的內存空間
?進程的同義詞有“程序”乔煞、“應用”吁朦,pipe、socket能夠為一個系統(tǒng)中的不同進程渡贾,或者不同系統(tǒng)中的多個進程逗宜。
2、線程
a空骚、輕量級的進程纺讲,存在于進程之中
b、線程與進程共享內存囤屹、打開的文件
對于開發(fā)者而言熬甚,啟動的線程只有一個,那就是main()肋坚。
Thread.slepp方法保證休眠的時間乡括,因為時間會受到底層操作系統(tǒng)的影響。同時智厌,休眠期間有可能會被Interrupt诲泌。
即使代碼中沒有使用可能拋出異常的方法,也可以顯式的判斷有沒有異常(比如用if)铣鹏,有的話進行處理敷扫。
isInterrupt方法在alive的線程未被Interrupt時,返回false;不是alive的線程被Interrupt時也返回false诚卸。
join()方法允許一個線程等待另一個線程執(zhí)行結束再繼續(xù)執(zhí)行葵第。
3、線程沖突
多個線程同時引用同一個對象合溺,并且操作不是原子操作的時候羹幸,有可能會出現線程沖突。
比如;i++操作,在jvm層面辫愉,該操作分為三步,多個線程同時執(zhí)行i++将硝,會出現interleave的情況恭朗,不能夠保證每次執(zhí)行(對應的jvm層面分解之后的操作)的順序都是一樣的屏镊。
4、內存不一致錯誤
對于多個線程共享的對象痰腮,一個線程對該對象寫內存之后而芥,對其他線程是可見的。
例如:Thread A的修改對Thread B 不可見(A膀值、B訪問同一個對象)
原始counter = 0;
A線程先執(zhí)行了counter++ ;但是B線程卻打印counter=0(正確情況應該是1)棍丐,那可能是因為A對counter的修改于B時不可見的,A沧踏、B之間并沒有建立起happens-before的關系歌逢。
解決方法:線程之間建立happens-before關系(比如使用join())。
5翘狱、同步方法
a秘案、需要有一個共同的對象
b、不能用在構造方法上潦匈,因為線程需要先創(chuàng)建對象然后再使用它阱高。即便如此,也需要避免對象過早泄露茬缩。例如在構造函數中使用instances.add(this)赤惊,在構造對象完成之前,其他的線程已經能夠通過instances訪問該對象凰锡。
final類型的變量未舟,對非同步方法而言是讀安全的,但是有可能會引起liveness的問題寡夹。
c处面、實現機制是使用了內部鎖(監(jiān)視鎖),來達到以下目的
1菩掏、強制對引用對象的獨占訪問
2魂角、建立起happens-before關系
d、如果同步方法是static的智绸,鎖為Class對象
6野揪、同步方法塊
a、需要指定一個對象充當內部鎖
b瞧栗、支持重入同步(同步方法塊中的代碼又調用了其他同步代碼塊中的代碼斯稳,而且都使用相同的鎖,循允許線程多次獲得同一把鎖來避免自身將自身阻塞)迹恐。
7挣惰、原子操作
1、操作要么完整執(zhí)行,要么根本不執(zhí)行憎茂,不存在中途停止執(zhí)行的情況珍语。
2、c++不是原子操作
3竖幔、原子操作不存在線程干擾問題板乙,但是有可能出現內存不一致問題。
4拳氢、所有的引用變量以及基本數據類型變量(除了long募逞、double)的讀寫操作都是原子操作。
5馋评、所有被volatile修飾的變量(包括long放接、double)的讀寫操作都是原子操作。