synchronized實現原理分析

synchronized是一個java關鍵字,底層是通過C++寫的,

synchronized應用場景

遇到線程安全問題時。如果程序中某代碼塊出現了線程不安全現象,可以加上synchronized鎖,從而保證線程安全;

synchronized基本特性

在普通方法上加上synchronized鎖,那麼其關聯的鎖對象是this鎖

<code>public synchronized void create(){
    count++;
    System.out.println(Thread.currentThread().getName()+","+count);
}/<code>

在靜態方法上加上synchronized鎖,那麼其關聯的鎖對象是class鎖

<code>public static synchronized void  create(){
    count++;
    System.out.println(Thread.currentThread().getName()+","+count);
}/<code>

當使用synchronized鎖同步代碼塊時,需要自定義鎖對象, 這個鎖對象是java的任意對象;

<code>private Object lockObject = new Object();
    
public void  create(){
   synchronized(lockObject){
      count++;
      System.out.println(Thread.currentThread().getName()+","+count);
   }
        
}/<code>

synchronized monitor對象源碼解讀

當使用synchronized關鍵字時,會觸發monitorenter和monitorexit兩個指令。

monitorenter: 官方描述

The objectref must be of type reference.

Each object is associated with a monitor. A monitor is locked if and only if it has an owner. The thread that executes monitorenter attempts to gain ownership of the monitor associated with objectref, as follows:

If the entry count of the monitor associated with objectref is zero, the thread enters the monitor and sets its entry count to one. The thread is then the owner of the monitor.

If the thread already owns the monitor associated with objectref, it reenters the monitor, incrementing its entry count.

If another thread already owns the monitor associated with objectref, the thread blocks until the monitor's entry count is zero, then tries again to gain ownership.


monitorexit:官方描述

The objectref must be of type reference.

The thread that executes monitorexit must be the owner of the monitor associated with the instance referenced by objectref.

The thread decrements the entry count of the monitor associated with objectref. If as a result the value of the entry count is zero, the thread exits the monitor and is no longer its owner. Other threads that are blocking to enter the monitor are allowed to attempt to do so.

DEMO:

<code>public class Test extends Thread {
    private Object lockObject = new Object();

    @Override
    public void run() {
        a();
    }

    public void a(){
        synchronized (lockObject){
            System.out.println("我是A調用B");
            b();
        }
    }

    public void b(){
        synchronized (lockObject){
            System.out.println("我是B");
        }
    }

}/<code>

彙編:javap -p -v Test.class

<code>public void a();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=3, args_size=1
         0: aload_0
         1: getfield      #4                  // Field lockObject:Ljava/lang/Object;
         4: dup
         5: astore_1
         6: monitorenter
         7: getstatic     #6                  // Field java/lang/System.out:Ljava/io/PrintStream;
        10: ldc           #7                  // String 我是A調用B
        12: invokevirtual #8                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
        15: aload_0
        16: invokevirtual #9                  // Method b:()V
        19: aload_1
        20: monitorexit
        21: goto          29
        24: astore_2
        25: aload_1
        26: monitorexit
        27: aload_2
        28: athrow
        29: return
      Exception table:
         from    to  target type
             7    21    24   any
            24    27    24   any
      LineNumberTable:
        line 18: 0
        line 19: 7
        line 20: 15
        line 21: 19
        line 22: 29
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      30     0  this   Lcom/test/Test005;
      StackMapTable: number_of_entries = 2
        frame_type = 255 /* full_frame */
          offset_delta = 24
          locals = [ class com/test/Test005, class java/lang/Object ]
          stack = [ class java/lang/Throwable ]
        frame_type = 250 /* chop */
          offset_delta = 4/<code>

monitor 常用屬性介紹、鎖池、等待池

在Java虛擬機(HotSpot)中,monitor是有ObjectMonitor實現的(C++實現的,位於HotSpot虛擬機源碼\openjdk8\openjdk\hotspot\src\share\vm\runtime\ObjectMonitor.hpp文件),其主要數據結構如下

<code> ObjectMonitor() {
    _header       = NULL;
    _count        = 0;  // 記錄個數
    _waiters      = 0,
    _recursions   = 0;   // 遞歸次數/重入次數
    _object       = NULL;
    _owner        = NULL; // 記錄當前持有鎖的線程ID
    _WaitSet      = NULL;  // 等待池:處於wait狀態的線程,會被加入到_WaitSet
    _WaitSetLock  = 0 ;
    _Responsible  = NULL ;
    _succ         = NULL ;
    _cxq          = NULL ;
    FreeNext      = NULL ;
    _EntryList    = NULL ;  // 鎖池:處於等待鎖block狀態的線程,會被加入到該列表
    _SpinFreq     = 0 ;
    _SpinClock    = 0 ;
    OwnerIsThread = 0 ;
   _previous_owner_tid = 0;
 }/<code>

synchronized對象佈局原理分析

java中new一個對象佔多少字節

synchronized鎖的升級過程

偏向鎖、輕量級鎖、自旋鎖、重量級鎖過程

synchronized使用需要注意的問題


分享到:


相關文章: