<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 加鎖 this 和 class 的區(qū)別!

          共 6560字,需瀏覽 14分鐘

           ·

          2021-08-02 10:54

          作者 | 王磊

          來源 | Java中文社群(ID:javacn666)

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

          synchronized 是 Java 語言中處理并發(fā)問題的一種常用手段,它也被我們親切的稱之為“Java 內(nèi)置鎖”,由此可見其地位之高。然而 synchronized 卻有著多種用法,當它修飾不同對象時,其意義也是不同的,下面我們一起來看。

          synchronized 用法

          synchronized 可以用來修飾普通方法、靜態(tài)方法和代碼塊。

          ① 修飾普通方法

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

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

          當 synchronized 修飾普通方法時,被修飾的方法被稱為同步方法,其作用范圍是整個方法,作用的對象是調(diào)用這個方法的對象。

          ② 修飾靜態(tài)方法

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

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

          當 synchronized 修飾靜態(tài)的方法時,其作用的范圍是整個方法,作用對象是調(diào)用這個類的所有對象。

          ③ 修飾代碼塊

          為了減少鎖的粒度,我們可以選擇在一個方法中的某個部分使用 synchronized 來修飾(一段代碼塊),從而實現(xiàn)對一個方法中的部分代碼進行加鎖,實現(xiàn)代碼如下:

          public void classMethod() throws InterruptedException {
          // 前置代碼...

          // 加鎖代碼
          synchronized (SynchronizedExample.class) {
          // ......
          }

          // 后置代碼...
          }

          以上代碼在執(zhí)行時,被修飾的代碼塊稱為同步語句塊,其作用范圍是大括號“{}”括起來的代碼塊,作用的對象是調(diào)用這個代碼塊的對象。

          但以上代碼,除了可以加鎖 class 之外,還可以加鎖 this,具體示例如下:

          public void classMethod() throws InterruptedException {
          // 前置處理代碼...
          synchronized (this) {
          // ......
          }
          // 后置處理代碼...
          }

          那問題來了,使用 synchronized 加鎖 this 和 class 的區(qū)別是什么?不都是加鎖同一個類嗎?

          答案還真不是,加鎖 this 和 class 區(qū)別還是很大的。下面我們通過以下 4 個示例,來看二者之間的區(qū)別。

          1.加鎖 class 共享一個類實例

          首先,我們創(chuàng)建 5 個線程,調(diào)用同一個對象下 synchronized 加鎖的 class 代碼,具體示例如下:

          import java.util.Date;
          import java.util.concurrent.TimeUnit;

          public class SynchronizedExample {

          public static void main(String[] args) {
          // 創(chuàng)建當前類實例
          final SynchronizedExample example = new SynchronizedExample();
          // 創(chuàng)建 5 個線程執(zhí)行任務
          for (int i = 0; i < 5; i++) {
          new Thread(new Runnable() {
          @Override
          public void run() {
          try {
          // 調(diào)用 synchronized 修飾的 class 方法
          example.classMethod();
          } catch (InterruptedException e) {
          e.printStackTrace();
          }
          }
          }).start();
          }
          }

          /**
          * synchronized 修飾的 class 方法
          * @throws InterruptedException
          */

          public void classMethod() throws InterruptedException {
          synchronized (SynchronizedExample.class) {
          System.out.println(String.format("當前執(zhí)行線程:%s,執(zhí)行時間:%s",
          Thread.currentThread().getName(), new Date()));
          TimeUnit.SECONDS.sleep(1);
          }
          }
          }

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

          從上述結(jié)果可以看出,這 5 個線程共享的是同一把鎖。

          2.加鎖 class 創(chuàng)建多個實例

          接下來,我們創(chuàng)建 5 個線程,調(diào)用不同對象下 synchronized 加鎖的 class 代碼,具體示例如下:

          import java.util.Date;
          import java.util.concurrent.TimeUnit;

          public class SynchronizedExample {

          public static void main(String[] args) {
          // 創(chuàng)建 5 個線程執(zhí)行任務
          for (int i = 0; i < 5; i++) {
          new Thread(new Runnable() {
          @Override
          public void run() {
          try {
          // 創(chuàng)建類實例
          SynchronizedExample example = new SynchronizedExample();
          // 調(diào)用 synchronized 修飾的 class 方法
          example.classMethod();
          } catch (InterruptedException e) {
          e.printStackTrace();
          }
          }
          }).start();
          }
          }

          /**
          * synchronized 修飾的 class 方法
          * @throws InterruptedException
          */

          public void classMethod() throws InterruptedException {
          synchronized (SynchronizedExample.class) {
          System.out.println(String.format("當前執(zhí)行線程:%s,執(zhí)行時間:%s",
          Thread.currentThread().getName(), new Date()));
          TimeUnit.SECONDS.sleep(1);
          }
          }
          }

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

          從上述結(jié)果可以看出,雖然是不同的對象,但它們使用的仍然是同一把鎖。

          3.加鎖 this 共享一個類實例

          接下來,我們創(chuàng)建 5 個線程,調(diào)用 synchronized 加鎖 this 的示例。首先我們這 5 個線程調(diào)用同一個對象的加鎖方法,示例代碼如下:

          import java.util.Date;
          import java.util.concurrent.TimeUnit;

          public class SynchronizedExample {

          public static void main(String[] args) {
          // 創(chuàng)建當前類實例
          final SynchronizedExample example = new SynchronizedExample();
          // 創(chuàng)建 5 個線程執(zhí)行任務
          for (int i = 0; i < 5; i++) {
          new Thread(new Runnable() {
          @Override
          public void run() {
          try {
          // 調(diào)用 synchronized 修飾的 this 方法
          example.thisMethod();
          } catch (InterruptedException e) {
          e.printStackTrace();
          }
          }
          }).start();
          }
          }

          /**
          * synchronized 修飾的 this 方法
          * @throws InterruptedException
          */

          public void thisMethod() throws InterruptedException {
          synchronized (this) {
          System.out.println(String.format("當前執(zhí)行線程:%s,執(zhí)行時間:%s",
          Thread.currentThread().getName(), new Date()));
          TimeUnit.SECONDS.sleep(1);
          }
          }
          }

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

          從上述結(jié)果可以看出,以上線程使用的都是同一把鎖。

          4.加鎖 this 創(chuàng)建多個類實例

          最后一個示例最為特殊,我們使用 synchronized 加鎖 this,讓這 5 個線程調(diào)用各自創(chuàng)建對象的方法,具體示例如下:

          import java.util.Date;
          import java.util.concurrent.TimeUnit;

          public class SynchronizedExample {

          public static void main(String[] args) {
          // 創(chuàng)建 5 個線程執(zhí)行任務
          for (int i = 0; i < 5; i++) {
          new Thread(new Runnable() {
          @Override
          public void run() {
          try {
          // 創(chuàng)建(多個)類實例
          SynchronizedExample example = new SynchronizedExample();
          // 調(diào)用 synchronized 修飾的 this 方法
          example.thisMethod();
          } catch (InterruptedException e) {
          e.printStackTrace();
          }
          }
          }).start();
          }
          }

          /**
          * synchronized 修飾的 this 方法
          * @throws InterruptedException
          */

          public void thisMethod() throws InterruptedException {
          synchronized (this) {
          System.out.println(String.format("當前執(zhí)行線程:%s,執(zhí)行時間:%s",
          Thread.currentThread().getName(), new Date()));
          TimeUnit.SECONDS.sleep(1);
          }
          }
          }

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



          從上述結(jié)果可以看出,當使用 synchronized 加鎖 this 時,如果線程調(diào)用的不是同一個對象,那么這些線程之間使用的鎖都是自己獨立的鎖,這個結(jié)果就和 synchronized 加鎖 class 的結(jié)果完全不同了。

          總結(jié)

          通過以上 4 個示例我們可以得出結(jié)論,當使用 synchronized 加鎖 class 時,無論共享一個對象還是創(chuàng)建多個對象,它們用的都是同一把鎖,而使用 synchronized 加鎖 this 時,只有同一個對象會使用同一把鎖,不同對象之間的鎖是不同的。

          本系列原創(chuàng)文章推薦

          1.線程的故事:我的3位母親成就了優(yōu)秀的我!
          2.線程池的7種創(chuàng)建方式,強烈推薦你用它...
          3.輕量級鎖一定比重量級鎖快嗎?
          4.這樣終止線程,竟然會導致服務宕機?
          5.漫畫:如何證明sleep不釋放鎖,而wait釋放鎖?
          6.池化技術(shù)到達有多牛?看了線程和線程池的對比嚇我一跳!
          7.求求你,別再用wait和notify了!
          8.Semaphore自白:限流器用我就對了!
          9.CountDownLatch:別浪,等人齊再團!
          10.CyclicBarrier:人齊了,老司機就發(fā)車了!
          11.Java中用戶線程和守護線程區(qū)別這么大?
          12.ThreadLocal不好用?那是你沒用對!
          13.ThreadLocal內(nèi)存溢出代碼演示和原因分析!
          14.SimpleDateFormat線程不安全的5種解決方案!


          瀏覽 36
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <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>
                  影音先锋中文字幕av | 亚洲 成人 在线 | 豆花成人理论在线电影一区二区 | 黄色毛片一区二区 | 嫖老熟女x88AV |