1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        synchronized 加鎖 this 和 class 的區(qū)別!

        共 6560字,需瀏覽 14分鐘

         ·

        2021-08-02 10:54

        作者 | 王磊

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

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

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

        synchronized 用法

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

        ① 修飾普通方法

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

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

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

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

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

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

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

        ③ 修飾代碼塊

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

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

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

        // 后置代碼...
        }

        以上代碼在執(zhí)行時(shí),被修飾的代碼塊稱(chēng)為同步語(yǔ)句塊,其作用范圍是大括號(hào)“{}”括起來(lái)的代碼塊,作用的對(duì)象是調(diào)用這個(gè)代碼塊的對(duì)象。

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

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

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

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

        1.加鎖 class 共享一個(gè)類(lèi)實(shí)例

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

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

        public class SynchronizedExample {

        public static void main(String[] args) {
        // 創(chuàng)建當(dāng)前類(lèi)實(shí)例
        final SynchronizedExample example = new SynchronizedExample();
        // 創(chuàng)建 5 個(gè)線程執(zhí)行任務(wù)
        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("當(dāng)前執(zhí)行線程:%s,執(zhí)行時(shí)間:%s",
        Thread.currentThread().getName(), new Date()));
        TimeUnit.SECONDS.sleep(1);
        }
        }
        }

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

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

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

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

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

        public class SynchronizedExample {

        public static void main(String[] args) {
        // 創(chuàng)建 5 個(gè)線程執(zhí)行任務(wù)
        for (int i = 0; i < 5; i++) {
        new Thread(new Runnable() {
        @Override
        public void run() {
        try {
        // 創(chuàng)建類(lèi)實(shí)例
        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("當(dāng)前執(zhí)行線程:%s,執(zhí)行時(shí)間:%s",
        Thread.currentThread().getName(), new Date()));
        TimeUnit.SECONDS.sleep(1);
        }
        }
        }

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

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

        3.加鎖 this 共享一個(gè)類(lèi)實(shí)例

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

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

        public class SynchronizedExample {

        public static void main(String[] args) {
        // 創(chuàng)建當(dāng)前類(lèi)實(shí)例
        final SynchronizedExample example = new SynchronizedExample();
        // 創(chuàng)建 5 個(gè)線程執(zhí)行任務(wù)
        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("當(dāng)前執(zhí)行線程:%s,執(zhí)行時(shí)間:%s",
        Thread.currentThread().getName(), new Date()));
        TimeUnit.SECONDS.sleep(1);
        }
        }
        }

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

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

        4.加鎖 this 創(chuàng)建多個(gè)類(lèi)實(shí)例

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

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

        public class SynchronizedExample {

        public static void main(String[] args) {
        // 創(chuàng)建 5 個(gè)線程執(zhí)行任務(wù)
        for (int i = 0; i < 5; i++) {
        new Thread(new Runnable() {
        @Override
        public void run() {
        try {
        // 創(chuàng)建(多個(gè))類(lèi)實(shí)例
        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("當(dāng)前執(zhí)行線程:%s,執(zhí)行時(shí)間:%s",
        Thread.currentThread().getName(), new Date()));
        TimeUnit.SECONDS.sleep(1);
        }
        }
        }

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



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

        總結(jié)

        通過(guò)以上 4 個(gè)示例我們可以得出結(jié)論,當(dāng)使用 synchronized 加鎖 class 時(shí),無(wú)論共享一個(gè)對(duì)象還是創(chuàng)建多個(gè)對(duì)象,它們用的都是同一把鎖,而使用 synchronized 加鎖 this 時(shí),只有同一個(gè)對(duì)象會(huì)使用同一把鎖,不同對(duì)象之間的鎖是不同的

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

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


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

        手機(jī)掃一掃分享

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

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            欧美三级日本三级 | 久久久久久久久一区二区三区 | 欧美肉体交换艳史 | 精品人妻一区二区三区浪潮无限 | 绿帽社区 | 欧美午夜视频在线观看 | 深爱激情综合 | 汤加丽裸体大乳照片 | t66y地址1地址2地址3 | 亚洲第一页在线观看 |