欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java并發(fā)編程中的synchronized解析

 更新時(shí)間:2023年11月01日 08:29:04   作者:南瓜燈cc  
這篇文章主要介紹了Java并發(fā)編程中的synchronized解析,synchronized是一個(gè)重量級(jí)的鎖,使用不當(dāng)?shù)脑捚鋵?shí)會(huì)使我們程序執(zhí)行的效率大打折扣,今天我們就對(duì)其進(jìn)行講解,需要的朋友可以參考下

一:synchronized的作用范圍

synchronized可作用在普通的方法上,靜態(tài)方法上以及同步代碼塊上。以下,我將分別的對(duì)這三種情況做一個(gè)分析。

1:作用于普通方法上

public class Demo01 implements Runnable{
    private int a;
    private synchronized void add() {
        a++;
    }

    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            add();
        }
    }

    public static void main(String[] args) {
        Demo01 demo01 =new Demo01();
        Thread thread1 =new Thread(demo01);
        Thread thread2 =new Thread(demo01);
        thread1.start();
        thread2.start();
    }
}

兩個(gè)線程對(duì)變量a各進(jìn)行100次的自加,在add方法上加了synchronized以達(dá)到線程間的同步效果。synchronized加在方法上,持有鎖的為該類的實(shí)例對(duì)象,即本例的demo01。所以兩個(gè)線程訪問同一個(gè)鎖對(duì)象會(huì)有互斥情況。 如果這里每個(gè)線程持有的為兩個(gè)不同的類實(shí)例,如下:

        Demo01 demo01 =new Demo01();
        Demo01 demo02 =new Demo01();
        Thread thread1 =new Thread(demo01);  //demo01
        Thread thread2 =new Thread(demo02);  //demo02

很明顯,這里在方法上加上synchronized來同步是不行的,因?yàn)檫@里是兩個(gè)new出來的不同的實(shí)例,如果想要通過的該類的不同實(shí)例來加鎖,我們可以通過下面的方式’。

2:作用于靜態(tài)方法上

我們知道靜態(tài)方法是歸屬于類所有的,同一個(gè)類的不同實(shí)例可以通過持有其類的相同Class來達(dá)到線程同步的效果。

如下:

public class Demo02 implements Runnable{
    private static int a;
    private synchronized static void add() {
        a++;
    }

    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            add();
        }
    }

    public static void main(String[] args) {
        Demo02 demo01 =new Demo02();
        Demo02 demo02 =new Demo02();
        Thread thread1 =new Thread(demo01);
        Thread thread2 =new Thread(demo02);
        thread1.start();
        thread2.start();
    }
}

創(chuàng)建線程使用的為同一個(gè)類的不同實(shí)例,調(diào)用靜態(tài)方法的時(shí)候,還是能夠達(dá)到線程同步的效果。因?yàn)榇藭r(shí)持有鎖對(duì)象的為類的Class字節(jié)碼。 除了上面兩種方式,還可以通過同步代碼塊的方式來進(jìn)行加鎖操作。

3:作用于同步代碼塊上

public class Demo03 implements Runnable{
    private  int a;
    private  void add() {
        synchronized (Object.class){
            a++;
        }
    }

    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            add();
        }
    }

    public static void main(String[] args) {
        Demo03 demo01 =new Demo03();
        Demo03 demo02 =new Demo03();
        Thread thread1 =new Thread(demo01);
        Thread thread2 =new Thread(demo02);
        thread1.start();
        thread2.start();
    }
}

以上例子持有鎖對(duì)象的為Object的Class,這里應(yīng)該注意的是,在同步代碼塊中,只要能夠保證每個(gè)線程過來時(shí),是同一個(gè)對(duì)象即可(任何類型的同一個(gè)實(shí)例對(duì)象)

二:synchronized同步的原理

synchronized的實(shí)現(xiàn)原理中,同步代碼塊與同步方法,同步靜態(tài)方法是不一樣的。在同步代碼塊中,是通過現(xiàn)實(shí)的監(jiān)視器對(duì)象來標(biāo)識(shí)的。而同步方法和同步靜態(tài)是通過同步方法來標(biāo)識(shí)的。通過查看其源碼的字節(jié)碼文件,我們可以清楚的看到其原理。

同步代碼塊字節(jié)碼文件:

  public void add();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=3, args_size=1
         0: aload_0
         1: dup
         2: astore_1
         3: monitorenter           //持有鎖
         4: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
         7: ldc           #3                  // String Aaa
         9: invokevirtual #4                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
        12: aload_1
        13: monitorexit          //釋放鎖
        14: goto          22
        17: astore_2
        18: aload_1
        19: monitorexit           //釋放鎖
        20: aload_2
        21: athrow
        22: return
      Exception table:
         from    to  target type
             4    14    17   any
            17    20    17   any
      LineNumberTable:
        line 6: 0
        line 7: 4
        line 8: 12
        line 9: 22
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      23     0  this   Lcom/sg/thread002/threadSynchronized/Demo04;
      StackMapTable: number_of_entries = 2
        frame_type = 255 /* full_frame */
          offset_delta = 17
          locals = [ class com/sg/thread002/threadSynchronized/Demo04, class java/lang/Object ]
          stack = [ class java/lang/Throwable ]
        frame_type = 250 /* chop */
          offset_delta = 4

可以看到同步代碼塊是直接顯示的執(zhí)行monitorenter和monitorexit ,JVM保證無論在什么情況下,執(zhí)行完同步的代碼塊,就會(huì)釋放鎖,所以會(huì)有兩個(gè)monitorexit,另一個(gè)則是保證在異常的時(shí)候也是能夠釋放掉鎖的。

同步普通方法與靜態(tài)方法:

  public static synchronized void add();
    descriptor: ()V
    //同步的標(biāo)識(shí)
    //ACC_PUBLIC :公共方法
    //ACC_STATIC :靜態(tài)方法
    //ACC_SYNCHRONIZED :同步方法標(biāo)識(shí)
    flags: ACC_PUBLIC, ACC_STATIC, ACC_SYNCHRONIZED
    Code:
      stack=2, locals=0, args_size=0
         0: getstatic     #2                  // Field a:I
         3: iconst_1
         4: iadd
         5: putstatic     #2                  // Field a:I
         8: return
      LineNumberTable:
        line 7: 0
        line 8: 8

這里可以看到在方法級(jí)別的同步是通過ACC_SYNCHRONIZED來標(biāo)識(shí)的。

到這里,關(guān)于synchronized就其使用的范圍以及原理做了一個(gè)分析,雖然說其是一個(gè)重量級(jí)的鎖,但是JDK在1.6的時(shí)候?qū)ζ溥M(jìn)行了優(yōu)化,引入的偏向鎖,提高其性能。于此同時(shí),synchronized也是一種可重入的鎖。

到此這篇關(guān)于Java并發(fā)編程中的synchronized解析的文章就介紹到這了,更多相關(guān)Java的synchronized解析內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java基礎(chǔ)篇之對(duì)象數(shù)組練習(xí)

    Java基礎(chǔ)篇之對(duì)象數(shù)組練習(xí)

    對(duì)象數(shù)組就是數(shù)組里的每個(gè)元素都是類的對(duì)象,賦值時(shí)先定義對(duì)象,然后將對(duì)象直接賦給數(shù)組就行了,這篇文章主要給大家介紹了關(guān)于Java基礎(chǔ)篇之對(duì)象數(shù)組練習(xí)的相關(guān)資料,需要的朋友可以參考下
    2024-03-03
  • Java程序中Doc文檔注釋示例教程

    Java程序中Doc文檔注釋示例教程

    這篇文章主要為大家介紹了Java程序中Doc文檔注釋的示例教程,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步
    2021-10-10
  • JAVA中關(guān)于Long類型返回前端精度丟失問題處理辦法

    JAVA中關(guān)于Long類型返回前端精度丟失問題處理辦法

    這篇文章主要介紹了后端JavaBean的id屬性從Long類型改為雪花算法后出現(xiàn)的精度丟失問題,解決方案包括將id字段類型改為字符串或使用Jackson序列化方式,需要的朋友可以參考下
    2024-11-11
  • Java實(shí)現(xiàn)泡泡堂對(duì)戰(zhàn)版游戲的示例代碼

    Java實(shí)現(xiàn)泡泡堂對(duì)戰(zhàn)版游戲的示例代碼

    本文將利用Java制作經(jīng)典游戲《泡泡堂》,文中使用了MVC模式,分離了模型、視圖和控制器,使得項(xiàng)目結(jié)構(gòu)清晰易于擴(kuò)展,感興趣的可以了解一下
    2022-04-04
  • java睡眠排序算法示例實(shí)現(xiàn)

    java睡眠排序算法示例實(shí)現(xiàn)

    這篇文章主要為大家介紹了java睡眠排序算法的示例實(shí)現(xiàn),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步
    2022-02-02
  • Spring Cloud Feign 自定義配置(重試、攔截與錯(cuò)誤碼處理) 代碼實(shí)踐

    Spring Cloud Feign 自定義配置(重試、攔截與錯(cuò)誤碼處理) 代碼實(shí)踐

    這篇文章主要介紹了Spring Cloud Feign 自定義配置(重試、攔截與錯(cuò)誤碼處理) 實(shí)踐,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-08-08
  • Java使用字節(jié)流復(fù)制文件的方法

    Java使用字節(jié)流復(fù)制文件的方法

    這篇文章主要為大家詳細(xì)介紹了Java使用字節(jié)流復(fù)制文件的方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-05-05
  • Java獲取磁盤空間的兩種代碼示例

    Java獲取磁盤空間的兩種代碼示例

    這篇文章主要介紹了Java獲取磁盤空間的兩種代碼示例,沒什么事的時(shí)候可以拿來玩玩,需要的朋友參考下。
    2017-11-11
  • 可能是全網(wǎng)最詳細(xì)的springboot整合minio教程

    可能是全網(wǎng)最詳細(xì)的springboot整合minio教程

    MinIO是全球領(lǐng)先的對(duì)象存儲(chǔ)先鋒,在標(biāo)準(zhǔn)硬件上,讀/寫速度上高達(dá)183 GB/秒和171 GB/秒,下面這篇文章主要給大家介紹了關(guān)于springboot整合minio的相關(guān)資料,這個(gè)教程可能是全網(wǎng)最詳細(xì)的,需要的朋友可以參考下
    2022-06-06
  • 10種java數(shù)組合并的常用方法總結(jié)

    10種java數(shù)組合并的常用方法總結(jié)

    在Java中,合并(或連接)數(shù)組是常見的任務(wù),這篇文章主要為大家整理了10個(gè)java中常用的數(shù)組合并方法,文中的示例代碼簡(jiǎn)潔易懂,需要的小伙伴可以參考下
    2023-12-12

最新評(píng)論