天天看點

java中鎖的概念

文章目錄

    • 使用者态與核心态
    • CAS 原理
    • 對于一個新建立的對象,整個對象在記憶體中的布局
    • 鎖的變化

java中鎖的概念

linux作業系統體系架構分為使用者态和核心态,核心控制計算機的硬體資源,并提供上層應用程式的運作1環境,使用者态即上層應用程式的活動空間,應用程式必須依托于核心提供的資源,對于輕量級别的鎖,經過使用者态,不經過核心态,重量級别的鎖在一定程度上會經過核心态

CAS : Compare and Swap 即比較再交換

CAS是一種無鎖的算法,有3個操作數,記憶體值V,舊的預期值A,要修改的新值B,當且隻當預期值A和記憶體值V相同時,将記憶體值V修改為B,否則什麼都不做

    public static void main(String[] args) throws InterruptedException {
        Thread[] threads = new Thread[100];
        CountDownLatch latch = new CountDownLatch(threads.length);

        for (int i = 0; i < threads.length; i++) {
            new Thread(() -> {
                for (int j = 0; j < 10000; j++) {
                    a.incrementAndGet();
                }
                latch.countDown();
            });
        }
        Arrays.stream(threads).forEach((t) -> t.start());
        latch.await();
        System.out.println(a);
    }      

其中a.incrementAndGet() 深入其中的源碼

  public final int incrementAndGet() {
        return unsafe.getAndAddInt(this, valueOffset, 1) + 1;
    }      

調用了 getAndAddInt

 public final int getAndAddInt(Object var1, long var2, int var4) {
        int var5;
        do {
            var5 = this.getIntVolatile(var1, var2);
        } while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));

        return var5;
    }      

compareAndSwapInt

  public final native boolean compareAndSwapInt(Object var1, long var2, int var4, int var5);      

對于java中的native關鍵字,凡是一種語言,都希望是純。比如解決某一個方案都喜歡就單單這個語言來寫即可。Java平台有個使用者和本地C代碼進行互操作的API,稱為Java Native Interface (Java本地接口)。

引入依賴

     <dependency>
            <groupId>org.openjdk.jol</groupId>
            <artifactId>jol-core</artifactId>
            <version>0.9</version>
        </dependency>      
        Object o = new Object();
        System.out.println(ClassLayout.parseInstance(o).toPrintable());      

結果

在這裡插入代碼片

java.lang.Object object internals:
 OFFSET  SIZE   TYPE DESCRIPTION                               VALUE
      0     4        (object header)                           01 00 00 00 (00000001 00000000 00000000 00000000) (1)
      4     4        (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)
      8     4        (object header)                           e5 01 00 f8 (11100101 00000001 00000000 11111000) (-134217243)
     12     4        (loss due to the next object alignment)Instance size: 16 bytesSpace losses: 0 bytes internal + 4 bytes external = 4 bytes total      

對于一個新建立的類,對64位的機器前8位為markword,後4位為class point 指定對象引用的類,由于沒有成員變量,是以隻有12位,故而往後補4位(loss due to the next object alignment),友善被8整除

将對象上鎖後的變化

synchronized (o){
            System.out.println(ClassLayout.parseInstance(o).toPrintable());
        }      
java.lang.Object object internals:
 OFFSET  SIZE   TYPE DESCRIPTION                               VALUE
      0     4        (object header)                           38 f7 66 03 (00111000 11110111 01100110 00000011) (57079608)
      4     4        (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)
      8     4        (object header)                           e5 01 00 f8 (11100101 00000001 00000000 11111000) (-134217243)
     12     4        (loss due to the next object alignment)Instance size: 16 bytesSpace losses: 0 bytes internal + 4 bytes external = 4 bytes total