2017-02-09 14 views
1

我對java中synchronized方法的理解,第一個線程獲取鎖對象,因此如果第二個線程檢查到它看到它正在使用並且「等待」,直到線程一完成,那麼鎖就會返回,而第二個線程可以獲得鎖並繼續。只要學習,如果這/關於簡化...這就是爲什麼。第二個線程如何檢查並重新檢查當前第一個線程使用的類的鎖定對象?

我的問題是第二個線程「等待」的內部機制是什麼......它是否繼續輪詢或重新檢查該鎖,直到它看到它的空閒狀態爲止?如果是這樣的話,這會影響一堆運行的線程而不是這個第一個/第二個例子嗎?或者它更像是一種註冊類型的機制,允許將第二個線程放入排序隊列中,然後在鎖定可用時通知它們?

只是好奇。謝謝!

回答

1

JVM處理內部鎖定的方式因地點而異,諸如JVM供應商,服務器/客戶端選項,活動線程,等待時間,隊列大小等因素......都被考慮到線程鎖定行爲上。

的熱點JDK VM特別的實施將是相當隱蔽的共同外行如我自己,我會在這裏離開這個做進一步的調查:http://hg.openjdk.java.net/jdk8u/jdk8u60/hotspot/file/37240c1019fd/src/share/vm/runtime/synchronizer.cpp

沒有深入到源代碼,據我所知內在鎖定保持不擁有鎖的等待線程的集合。如果線程嘗試獲取並失敗,則將其添加到此集合中,並且可能執行一些不同的操作:

  1. 自旋,許多算法都可以在這裏。當旋轉成功獲取鎖定時通知第二個線程。
  2. 上下文切換,暫停線程並釋放處理器。退出線程通知下一個服務員。
  3. 睡覺,暫停線程但保留處理器。與2相同。

線程將執行的操作通常由啓發式或線程獲取的任何類型的鎖確定。系統還可以結合不同的方法,例如在睡覺前旋轉N次,然後進行上下文切換。這是依賴於系統的。由於我找不到支持我所說的任何參考資料,所以我可能會錯誤地提出一些或所有的觀點。

老實說,對於Java開發人員來說,鎖定的內部實現應該至關重要。 JVM的線程調度和鎖定非常高效,使用這些算法的工程師非常聰明,可以花費數週,數月和數年測試,並確保實現提供最佳性能。這就是爲什麼最低級別的線程控制來自thread parking,任何更低的你都需要JNI或不同的語言。如果您正在實施自己的同步器,請考慮使用AbstractQueuedSynchronizerJDK source有詳細的記錄,您將看到非內在鎖和其他高級同步程序(如ReentrantLock)是如何工作的。

編輯

JVM的具體實現路徑發生像這樣:

  1. 運行/同步。CPP
  2. High level spin
  3. Call to park event
  4. OS電話:
  5. 僅限Linux:NPTL - >Futex syscall
1

我的問題是第二個線程「等待」的內部機制是什麼......它是否繼續輪詢或重新檢查該鎖,直到它看到它的空閒狀態爲止?

這在大多數情況下不是由JVM完全處理,而是由OS中的線程層處理。也就是說,線程當然不是輪詢。當第二個線程遇到一個已經被鎖定的鎖時,它將停止運行,並被放入與該鎖相關的有序等待隊列中。當鎖被解鎖時,等待隊列中的第一個線程(如果有的話)被喚醒並移入運行隊列。

如果是這樣的話,這會影響一堆運行的線程而不是第一個/第二個例子嗎?

否。隊列可以很好地擴展到大量的線程。

或者它更多的是一種註冊類型的機制,允許第二個線程放入一個排序隊列中,然後在鎖定可用時通知?

沒錯。線程完全停止運行,解鎖鎖的線程是啓動線程再次運行的線程(或某種管理程序線程)。

相關問題