線程基礎----java對象鎖(三)

前言:

      關於對象鎖,在網上看了不少文章,但都說了不是很清楚。因而查看資料,發現只有從jvm角度講對象鎖纔會容易理解。java

正文:

     java虛擬機的一些運行時數據區會被全部的線程共享,其餘數據時各個線程私有的,由於堆和方法區是被全部線程所共享的,java程序須要爲兩種多線程訪問數據進行協調:編程

  • 保存在堆中的實例變量
  • 保存在方法區中的類變量

     程序不須要協調保存在java棧中的局部變量,由於java棧中的數據時屬於擁有該棧的線程的私有的。安全

java虛擬機的內部體系結構

jvm

如下文字摘自《深刻java虛擬機》

   在java虛擬機中,每一個對象和類在邏輯上都是和一個監視器相關聯的。對於對象來講,相關聯的監視器保護對象的實例變量,對於類來講,監視器保護類的類變量。若是一個對象沒有實例變量。或者一個類沒有類變量,相關聯的監視器就什麼都不監視(補充:變量其實就是數據,加上監視器主要是爲了數據安全,一致)。多線程

     爲了實現監視器的排他性監視能力,java虛擬機爲每一個對象和類都關聯一個鎖(有時候被稱爲互斥體(mutex))。一個鎖就像一種任什麼時候候只容許一個線程「擁有特權」。線程訪問實例變量或者類變量就不須要獲取鎖,可是若是獲取了鎖,那麼他釋放這個鎖以前,就沒有其餘線程能夠獲取一樣數據的鎖了。(「鎖住一個對象」就是獲取對象相關聯的監視器。)jvm

    類鎖實際上用對象鎖實現。當java虛擬機轉載一個class文件的時候,他會建立一個java.lang.Class類的實例。當鎖住一個類的時候,實際上鎖住的是那個類的class對象。.net

    一個線程能夠運行屢次對同一個對象上鎖。對於每個對象來講,java虛擬機維護一個計數器,記錄對象被加了多少次鎖。沒有被鎖的對象計數器爲0.但第一個線程第一次獲取鎖的時候,計數器跳到1,線程每加一次鎖一次,計數器就加1.(只有已經擁有了這個對象的鎖的線程才能對該對象再次枷鎖。在它釋放鎖以前,其餘線程不能對這個對象枷鎖)每當線程釋放鎖一次,計數器就減一。當計數器跳到0的時候,鎖就跳到0的時候,鎖就被徹底釋放了,其餘線程纔可使用它。線程

   java虛擬機中的一個線程在它到達監視區域開始處的時候請求一個鎖。在java中,有兩種監視區域:同步語句和同步方法(這些在本章後面會詳細描述)。java程序中的每個監視區域都和一個對象引用相關聯。當一個線程到達監視區域的第一條指令的時候,線程必須對改引用對象枷鎖,不然線程不容許執行其中的代碼,一旦它得到了鎖,線程就進入了被保護的代碼。當線程離開這塊代碼的時候,無論它是如何離開的,它都會釋放相關對象的鎖。對象

注意:java編程人員不須要手動枷鎖,對象鎖是在java虛擬機內部使用的。在java程序中,你只須要編寫同步語句,或者同步方法,就能夠標示一個監視區域。當java虛擬機運行你的程序的時候,每一次進入一個監視區域的時候,它每次都會自動鎖上對象或者類。get

相關文章
相關標籤/搜索