<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          synchronized 幾種用法,你很有必要知道

          共 5163字,需瀏覽 11分鐘

           ·

          2022-04-13 18:12

          6f795d8bd9ae2066260e2ff4a2013cfd.webp

          78bf70b6f154ae24984d99195c9703a6.webp

          作者 | 磊哥

          來(lái)源 | Java面試真題解析(ID:aimianshi666)

          轉(zhuǎn)載請(qǐng)聯(lián)系授權(quán)(微信ID:GG_Stone)

          在 Java 語(yǔ)言中,保證線程安全性的主要手段是加鎖,而 Java 中的鎖主要有兩種:synchronized 和 Lock,我們今天重點(diǎn)來(lái)看一下 synchronized 的幾種用法。

          用法簡(jiǎn)介

          使用 synchronized 無(wú)需手動(dòng)執(zhí)行加鎖和釋放鎖的操作,我們只需要聲明 synchronized 關(guān)鍵字就可以了,JVM 層面會(huì)幫我們自動(dòng)的進(jìn)行加鎖和釋放鎖的操作。synchronized 可用于修飾普通方法、靜態(tài)方法和代碼塊,接下來(lái)我們分別來(lái)看。

          1、修飾普通方法

          synchronized 修飾普通方法的用法如下:

          /**
          ?*?synchronized?修飾普通方法
          ?*/

          public?synchronized?void?method()?{
          ????//?....
          }

          當(dāng) synchronized 修飾普通方法時(shí),被修飾的方法被稱為同步方法,其作用范圍是整個(gè)方法,作用的對(duì)象是調(diào)用這個(gè)方法的對(duì)象。

          2、修飾靜態(tài)方法

          synchronized 修飾靜態(tài)方法和修飾普通方法類似,它的用法如下:

          /**
          ?*?synchronized?修飾靜態(tài)方法
          ?*/

          public?static?synchronized?void?staticMethod()?{
          ????//?.......
          }

          當(dāng) synchronized 修飾靜態(tài)方法時(shí),其作用范圍是整個(gè)程序,這個(gè)鎖對(duì)于所有調(diào)用這個(gè)鎖的對(duì)象都是互斥的。

          所謂的互斥,指的是同一時(shí)間只能有一個(gè)線程能使用,其他線程只能排隊(duì)等待。

          修飾普通方法 VS 修飾靜態(tài)方法

          synchronized 修飾普通方法和靜態(tài)方法看似相同,但二者完全不同,對(duì)于靜態(tài)方法來(lái)說(shuō) synchronized 加鎖是全局的,也就是整個(gè)程序運(yùn)行期間,所有調(diào)用這個(gè)靜態(tài)方法的對(duì)象都是互斥的,而普通方法是針對(duì)對(duì)象級(jí)別的,不同的對(duì)象對(duì)應(yīng)著不同的鎖,比如以下代碼,同樣是調(diào)用兩次方法,但鎖的獲取完全不同,實(shí)現(xiàn)代碼如下:

          import?java.time.LocalDateTime;
          import?java.util.concurrent.ExecutorService;
          import?java.util.concurrent.Executors;
          import?java.util.concurrent.TimeUnit;

          public?class?SynchronizedUsage?{
          ????public?static?void?main(String[]?args)?throws?InterruptedException?{
          ????????//?創(chuàng)建線程池同時(shí)執(zhí)行任務(wù)
          ????????ExecutorService?threadPool?=?Executors.newFixedThreadPool(10);

          ????????//?執(zhí)行兩次靜態(tài)方法
          ????????threadPool.execute(()?->?{
          ????????????staticMethod();
          ????????});
          ????????threadPool.execute(()?->?{
          ????????????staticMethod();
          ????????});
          ????????
          ????????//?執(zhí)行兩次普通方法
          ????????threadPool.execute(()?->?{
          ????????????SynchronizedUsage?usage?=?new?SynchronizedUsage();
          ????????????usage.method();
          ????????});
          ????????threadPool.execute(()?->?{
          ????????????SynchronizedUsage?usage2?=?new?SynchronizedUsage();
          ????????????usage2.method();
          ????????});
          ????}

          ????/**
          ?????*?synchronized?修飾普通方法
          ?????*?本方法的執(zhí)行需要?3s(因?yàn)橛?3s?的休眠時(shí)間)
          ?????*/

          ????public?synchronized?void?method()?{
          ????????System.out.println("普通方法執(zhí)行時(shí)間:"?+?LocalDateTime.now());
          ????????try?{
          ????????????//?休眠?3s
          ????????????TimeUnit.SECONDS.sleep(3);
          ????????}?catch?(InterruptedException?e)?{
          ????????????e.printStackTrace();
          ????????}
          ????}

          ????/**
          ?????*?synchronized?修飾靜態(tài)方法
          ?????*?本方法的執(zhí)行需要?3s(因?yàn)橛?3s?的休眠時(shí)間)
          ?????*/

          ????public?static?synchronized?void?staticMethod()?{
          ????????System.out.println("靜態(tài)方法執(zhí)行時(shí)間:"?+?LocalDateTime.now());
          ????????try?{
          ????????????//?休眠?3s
          ????????????TimeUnit.SECONDS.sleep(3);
          ????????}?catch?(InterruptedException?e)?{
          ????????????e.printStackTrace();
          ????????}
          ????}
          }

          以上程序的執(zhí)行結(jié)果如下:836eeca2535b6ea79a8d7275380a6df8.webp從上述結(jié)果可以看出,靜態(tài)方法加鎖是全局的,針對(duì)的是所有調(diào)用者;而普通方法加鎖是對(duì)象級(jí)別的,不同的對(duì)象擁有的鎖也不同。

          3、修飾代碼塊

          我們?cè)谌粘i_發(fā)中,最常用的是給代碼塊加鎖,而不是給方法加鎖,因?yàn)榻o方法加鎖,相當(dāng)于給整個(gè)方法全部加鎖,這樣的話鎖的粒度就太大了,程序的執(zhí)行性能就會(huì)受到影響,所以通常情況下,我們會(huì)使用 synchronized 給代碼塊加鎖,它的實(shí)現(xiàn)語(yǔ)法如下:

          public?void?classMethod()?throws?InterruptedException?{
          ????//?前置代碼...
          ????
          ????//?加鎖代碼
          ????synchronized?(SynchronizedUsage.class)?{
          ????????//?......
          ????}
          ????
          ????//?后置代碼...
          }

          從上述代碼我們可以看出,相比于修飾方法,修飾代碼塊需要自己手動(dòng)指定加鎖對(duì)象,加鎖的對(duì)象通常使用 this 或 xxx.class 這樣的形式來(lái)表示,比如以下代碼:

          //?加鎖某個(gè)類
          synchronized?(SynchronizedUsage.class)?{
          ????//?......
          }

          //?加鎖當(dāng)前類對(duì)象
          synchronized?(this)?{
          ????//?......
          }

          this VS class

          使用 synchronized 加鎖 this 和 xxx.class 是完全不同的,當(dāng)加鎖 this 時(shí),表示用當(dāng)前的對(duì)象進(jìn)行加鎖,每個(gè)對(duì)象都對(duì)應(yīng)了一把鎖;而當(dāng)使用 xxx.class 加鎖時(shí),表示使用某個(gè)類(而非類實(shí)例)來(lái)加鎖,它是應(yīng)用程序級(jí)別的,是全局生效的,如以下代碼所示:

          import?java.time.LocalDateTime;
          import?java.util.concurrent.ExecutorService;
          import?java.util.concurrent.Executors;
          import?java.util.concurrent.TimeUnit;

          public?class?SynchronizedUsageBlock?{
          ????public?static?void?main(String[]?args)?throws?InterruptedException?{
          ????????//?創(chuàng)建線程池同時(shí)執(zhí)行任務(wù)
          ????????ExecutorService?threadPool?=?Executors.newFixedThreadPool(10);

          ????????//?執(zhí)行兩次?synchronized(this)
          ????????threadPool.execute(()?->?{
          ????????????SynchronizedUsageBlock?usage?=?new?SynchronizedUsageBlock();
          ????????????usage.thisMethod();
          ????????});
          ????????threadPool.execute(()?->?{
          ????????????SynchronizedUsageBlock?usage2?=?new?SynchronizedUsageBlock();
          ????????????usage2.thisMethod();
          ????????});

          ????????//?執(zhí)行兩次?synchronized(xxx.class)
          ????????threadPool.execute(()?->?{
          ????????????SynchronizedUsageBlock?usage3?=?new?SynchronizedUsageBlock();
          ????????????usage3.classMethod();
          ????????});
          ????????threadPool.execute(()?->?{
          ????????????SynchronizedUsageBlock?usage4?=?new?SynchronizedUsageBlock();
          ????????????usage4.classMethod();
          ????????});
          ????}

          ????/**
          ?????*?synchronized(this)?加鎖
          ?????*?本方法的執(zhí)行需要?3s(因?yàn)橛?3s?的休眠時(shí)間)
          ?????*/

          ????public?void?thisMethod()?{
          ????????synchronized?(this)?{
          ????????????System.out.println("synchronized(this)?加鎖:"?+?LocalDateTime.now());
          ????????????try?{
          ????????????????//?休眠?3s
          ????????????????TimeUnit.SECONDS.sleep(3);
          ????????????}?catch?(InterruptedException?e)?{
          ????????????????e.printStackTrace();
          ????????????}
          ????????}
          ????}

          ????/**
          ?????*?synchronized(xxx.class)?加鎖
          ?????*?本方法的執(zhí)行需要?3s(因?yàn)橛?3s?的休眠時(shí)間)
          ?????*/

          ????public?void?classMethod()?{
          ????????synchronized?(SynchronizedUsageBlock.class)?{
          ????????????System.out.println("synchronized(xxx.class)?加鎖:"?+?LocalDateTime.now());
          ????????????try?{
          ????????????????//?休眠?3s
          ????????????????TimeUnit.SECONDS.sleep(3);
          ????????????}?catch?(InterruptedException?e)?{
          ????????????????e.printStackTrace();
          ????????????}
          ????????}
          ????}
          }

          以上程序的執(zhí)行結(jié)果如下:438f17385b3deb485870dbc109633fd9.webp

          總結(jié)

          synchronized 用 3 種用法,用它可以來(lái)修飾普通方法、靜態(tài)方法和代碼塊,其中最常用的是修飾代碼塊,而修飾代碼塊時(shí)需要指定一個(gè)加鎖對(duì)象,這個(gè)加鎖對(duì)象通常使用 this 或 xxx.class 來(lái)表示,當(dāng)使用 this 時(shí),表示使用當(dāng)前對(duì)象來(lái)加鎖,而使用 class 時(shí),表示表示使用某個(gè)類(非類對(duì)象實(shí)例)來(lái)加鎖,它是全局生效的。



          aabf6ee8d91723cde97de8d8b470c5fa.webp


          1. ?2022:請(qǐng)對(duì)我的 Flag 好一點(diǎn)!

          2. 30歲生日,總結(jié)過去的一年,我哭了……

          9d0987ff6f0846a9c5ae01838d5d62db.webp

          瀏覽 30
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  91精品久久久久久久久久久久 | 操逼精品| 在线观看一区二区三区四区五区 | 俺去也视频 | 大香蕉伊人成人电影 |