⑴ synchronized關鍵字的作用、原理以及鎖優化
synchronized關鍵字主要作用於java中的線程同步,確保線程安全,通過內部鎖機制實現。它可以用於修飾代碼塊或方法。內部鎖在Java中扮演著互斥鎖的角色,同一時刻最多隻有一個線程能獲取鎖。內部鎖在進入synchronized代碼塊時自動獲取,線程退出或拋出異常時釋放。除了確保線程同步,synchronized還保證了線程間的可見性和有序性。
synchronized關鍵字有三種使用方式:修飾代碼塊、實例方法或靜態方法。修飾代碼塊時,鎖的對象為指定的對象實例。實例方法時,鎖的對象為當前實例。靜態方法時,鎖的對象為類的實例,而非當前實例。錯誤示例2.1通過將方法修飾為靜態方法,可以實現正確的同步,無論指向的實例如何。
synchronized的底層原理是通過Javac編譯後的位元組碼實現。在同步塊的前後分別形成monitorenter和monitorexit指令,這兩個指令需要一個reference類型的參數來指明要鎖定和解鎖的對象。執行monitorenter指令時,首先嘗試獲取對象的鎖,如果成功,將鎖的計數器增加一。執行monitorexit指令時,將鎖計數器減一,當計數器為零時,鎖被釋放。獲取鎖失敗時,線程被阻塞等待。
synchronized修飾的方法沒有monitorenter和monitorexit指令,而是通過ACC_SYNCHRONIZED標識來識別為同步方法。JVM通過這個標識來執行同步調用。
JDK1.6之後,HotSpot虛擬機團隊實現了一系列鎖優化技術,如適應性自旋鎖、鎖消除、鎖粗化、輕量級鎖、偏向鎖等,以提高鎖的效率。這些優化技術主要針對鎖的獲取和釋放過程進行改進。
偏向鎖是通過消除無競爭情況下的同步原語來優化性能。當一個線程獲取鎖後,鎖進入偏向模式,後續請求鎖的線程無須進行任何同步操作。連續多次請求相同鎖的線程可以享受偏向鎖帶來的性能提升。一旦有其他線程請求鎖,偏向模式失效,鎖狀態被撤銷。使用Java虛擬機參數-XX:+UseBiasedLocking可以開啟偏向鎖。
輕量級鎖通過使用CAS操作來實現加鎖和解鎖。輕量級鎖在鎖競爭失敗時,如果鎖對象的狀態為偏向鎖狀態,會直接將偏向鎖升級為輕量級鎖,並嘗試使用自旋獲取鎖。輕量級鎖在解鎖時,會將Displaced Mark Word替換回對象頭。如果成功,表示沒有競爭發生。如果失敗,表示存在競爭,鎖會膨脹成重量級鎖。
自旋鎖和自適應自旋是一種優化手段,當線程獲取鎖失敗時,不會立即掛起線程,而是讓線程在處理器上進行幾個空循環(自旋)。如果獲取到鎖,線程進入同步塊。自旋鎖在JDK1.6及之後默認開啟。自適應自旋則是根據前一次在同一個鎖上的自旋時間以及鎖的擁有者的狀態來決定自旋等待的時間,以提高性能。
鎖消除是另一種優化技術,虛擬機即時編譯器在運行時對代碼進行分析,如果判斷到一段代碼中,在堆上所有數據都不會被其他線程訪問到,可以將同步操作消除。逃逸分析是鎖消除的主要依據,需要在-server模式下進行。使用-XX:+DoEscapeAnalysis參數開啟逃逸分析,-XX:+EliminateLocks參數開啟鎖消除。
鎖粗化是指虛擬機探測到一系列連續操作都對同一個對象反復加鎖和解鎖時,將加鎖同步返回擴展到整個操作序列的外部,只需要加鎖一次。這可以減少不必要的性能損耗。
⑵ Java怎麼使用synchronized聲明一個變數
首先要說明的是,java里不能直接使用synchronized聲明一個變數,而是使用synchronized去修飾一個代碼塊或一個方法。x0dx0ax0dx0a詳細說明如下:x0dx0ax0dx0a synchronized用來修飾一個方法或者一個代碼塊,它用來保證在同一時刻最多隻有一個線程執行該段代碼。x0dx0a 一、當兩個並發線程訪問同一個對象object中的這個synchronized(this)同步代碼塊時,一個時間內只能有一個線程得到執行。另簡圓一個線程必須等待當前線程執行完這個代碼塊以後才能執行該代碼塊。x0dx0a 二、然而,當一個線程訪問object的一個synchronized(this)同步代碼塊時,另一個線程仍然可以訪問該object中的非synchronized(this)同步代碼塊。x0dx0a 三、尤其關鍵的是,當一個線程訪問object的一個synchronized(this)同步代碼塊時,其他線程對object中所有其它synchronized(this)同步代碼塊的訪明悉問將被阻塞。x0dx0a 四、第三激咐乎個例子同樣適用其它同步代碼塊。也就是說,當一個線程訪問object的一個synchronized(this)同步代碼塊時,它就獲得了這個object的對象鎖。結果,其它線程對該object對象所有同步代碼部分的訪問都被暫時阻塞。x0dx0a 五、以上規則對其它對象鎖同樣適用。x0dx0ax0dx0a示例代碼:x0dx0apublic class Thread1 implements Runnable { x0dx0a public void run() { x0dx0a synchronized(this) { x0dx0a for (int i = 0; i < 5; i++) { x0dx0a System.out.println(Thread.currentThread().getName() + " synchronized loop " + i); x0dx0a } x0dx0a } x0dx0a } x0dx0a public static void main(String[] args) { x0dx0a Thread1 t1 = new Thread1(); x0dx0a Thread ta = new Thread(t1, "A"); x0dx0a Thread tb = new Thread(t1, "B"); x0dx0a ta.start(); x0dx0a tb.start(); x0dx0a }x0dx0a}x0dx0a結果: x0dx0a A synchronized loop 0 x0dx0a A synchronized loop 1 x0dx0a A synchronized loop 2 x0dx0a A synchronized loop 3 x0dx0a A synchronized loop 4 x0dx0a B synchronized loop 0 x0dx0a B synchronized loop 1 x0dx0a B synchronized loop 2 x0dx0a B synchronized loop 3 x0dx0a B synchronized loop 4
⑶ java中的synchronized()的具體作用
synchronized()
作用是:防止多個線程同一時間調用此代碼塊或者方法.