1. 多線程的3中運行方式:java
2. synchronized是一個重量級鎖程序員
3. sychronized的鎖類型 和 位置數據結構
java 爲每一個類實例和類都設置了一個鎖而且遵循必定的鎖機制。多線程
在分析sychronized 邏輯是,關鍵點就是分析出提供鎖的對象是哪一個?實例,仍是類優化
Java中每個對象均可以做爲鎖,這是synchronized實現同步的基礎: this
1. 普通同步方法,鎖是當前實例對象 spa
2. 靜態同步方法,鎖是當前類的class對象 .net
3. 同步方法塊,鎖是括號裏面的對象(某個實例對象或者class對象)線程
4.synchronized 實現原理(javap filename.class)翻譯
同步代碼塊:monitorenter指令插入到同步代碼塊的開始位置,monitorexit指令插入到同步代碼塊的結束位置。
每一個對象有一個監視器鎖(monitor)。當monitor被佔用時就會處於鎖定狀態,線程執行monitorenter指令
時嘗試獲取monitor的全部權,過程以下:
1.若是monitor的進入數爲0,則該線程進入monitor,而後將進入數設置爲1,該線程即爲monitor的全部者。
2.若是線程已經佔有該monitor,只是從新進入,則進入monitor的進入數加1.
3.若是其餘線程已經佔用了monitor,則該線程進入阻塞狀態,直到monitor的進入數爲0,再從新嘗試獲取monitor的全部權。
執行monitorexit的線程必須是objectref所對應的monitor的全部者。
monitor的進入數減1,若是減1後進入數爲0。
同步方法: synchronized方法則會被翻譯成普通的方法調用和返回指令如:invokevirtual、areturn指令,在VM字節碼層面並無任何
特別的指令來實現被synchronized修飾的方法,而是在Class文件的方法表中將該方法的access_flags字段中的synchronized
標誌位置1。若是設置了,執行線程將先獲取monitor。並無經過指令monitorenter和monitorexit來完成
Java對象頭和monitor是實現synchronized的基礎:
Hotspot虛擬機的對象頭主要包括兩部分數據:Mark Word(標記字段)、Klass Pointer(類型指針)。
其中Klass Point是是對象指向它的類元數據的指針,虛擬機經過這個指針來肯定這個對象是哪一個類的實例,
Mark Word用於存儲對象自身的運行時數據,它是實現輕量級鎖和偏向鎖的關鍵,因此下面將重點闡述
Mark Word用於存儲對象自身的運行時數據,如哈希碼(HashCode)、GC分代年齡、鎖狀態標誌、線程持
有的鎖、偏向線程 ID、偏向時間戳等等。
Monitor 是線程私有的數據結構,每個線程都有一個可用monitor record列表,同時還有一個全局的可用列表。
每個被鎖住的對象都會和一個monitor關聯(對象頭的MarkWord中的LockWord指向monitor的起始地址),
同時monitor中有一個Owner字段存放擁有該鎖的線程的惟一標識,表示該鎖被這個線程佔用。其結構以下:
JDK1.6後對synchronized的優化:
自旋鎖,自適應自旋鎖
鎖消除
鎖粗化
輕量級鎖 偏向鎖 鎖釋放
JAVA線程操做之 wait notify notifyAll condition,生產者消費者
JAVA線程操做之 interruppt isInterrupted interruppted
(1)interrupt:調用此方法的線程的狀態屬性置爲「interrupted」,interrupt()並不會中斷一個正在運行的線程,或者說讓一個running中的線程放棄CPU。
調用此方法,若是線程處於阻塞狀態,那麼線程將會拋出InterruptedException異常
應用場景:
*this.interruppt()線程自己並不會馬上終止。程序員須要根據這個狀態屬性,自行決定如何進行線程的下一步活動。
由於Core Java中有這樣一句話:"沒有任何語言方面的需求要求一個被中斷的程序應該終止。中斷一個線程只是爲
了引發該線程的注意,被中斷線程能夠決定如何應對中斷 "。因此Thread.stop(),suspend(), resume(),runFinalizersOnExit()
被廢棄了。
*使用Thread.interrupt()中斷可能永久的阻塞線程(Object.wait()、ServerSocket.accept())。
或者須要用某種機制使得線程更早地退出被阻塞的狀態.
(2)isInterrupted:線程是否中斷 native 方法
(3)interrupted:*返回線程的上次的中斷狀態,並清除中斷狀態。就是若是狀態位是true(isInterrupted()=true),則interrupted()返回的
結果是true,可是同時把狀態爲設置成false,再調用isInterrupted()會返回false.
*只有當前線程才能清除本身的中斷位(對應interrupted()方法) 意思是interrupted()不可能像 TreadA.isInterrupted() 或者TreadA.interrupt()同樣使用,而是在本身的run方法裏面 直接interrupted();