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

Java中synchronized的四種用法詳解

 更新時(shí)間:2024年01月23日 08:45:02   作者:碼靈  
這篇文章主要介紹了Java中synchronized的四種用法詳解,當(dāng)我們處理多線程處理同步問題的時(shí)候就會用到synchronized這個(gè)關(guān)鍵字,下面介紹下synchronized的四種用法,需要的朋友可以參考下

問題描述

介紹之前我們先來看下,在java 多線程中 如果沒有線程同步會出現(xiàn)什么問題:

下面這個(gè)是一個(gè)測試?yán)樱?/p>

public class MainClass {    public static class MyRun implements Runnable    {        private int count=0;        @Override        public void run() {            while (count<15)            {                    System.out.print("ThreadName:"+Thread.currentThread().getName()+"  count:"+count+"\n");                    count++;                         try {                        Thread.sleep(200);                    }                    catch (Exception e)                    {                    }            }        }    }    public  static void main(String args[])    {          MyRun myRun=new MyRun();        Thread threadA=new Thread(myRun,"A");        Thread threadB=new Thread(myRun,"B");        threadA.start();        threadB.start();    }}

運(yùn)行結(jié)果

ThreadName:A  count:0

ThreadName:B  count:0

ThreadName:A  count:1

ThreadName:A  count:3

ThreadName:B  count:2

ThreadName:A  count:4

ThreadName:A  count:6

ThreadName:A  count:7

ThreadName:B  count:5

我們看到這個(gè)count在無序的增加,這個(gè)是由于A,B兩個(gè)線程同時(shí)操作Count變量造成的,如果我們想讓Count有序增加,應(yīng)該給

System.out.print("ThreadName:"+Thread.currentThread().getName()+"  count:"+count+"\n");
count++;

這段代碼同步枷鎖,這樣當(dāng)B線程進(jìn)入這里時(shí)候,發(fā)現(xiàn)這里已經(jīng)被鎖,就只有等待,A執(zhí)行完這段代碼之后就會釋放對這個(gè)對象的這段代碼的釋放鎖,A獲得了釋放鎖,就可以進(jìn)入執(zhí)行,讓A,B有序進(jìn)入執(zhí)行,才能讓Count有序增加,加入了synchronized之后的代碼:

 while (count<15) {
                    synchronized (this)
                    {
                        System.out.print("ThreadName:"+Thread.currentThread().getName()+"  count:"+count+"\n");
                        count++;
                    }
                    try {
                        Thread.sleep(200);
                    }
                    catch (Exception e)
                    {
                    }
            }

結(jié)果:

ThreadName:A  count:0

ThreadName:B  count:1

ThreadName:B  count:2

ThreadName:A  count:3

ThreadName:A  count:4

ThreadName:B  count:5

ThreadName:B  count:6

ThreadName:A  count:7

ThreadName:B  count:8

加了鎖之后A,B線程就可以有序的交替執(zhí)行,不會同時(shí)搶占執(zhí)行Count++ 操作,

下面介紹synchronised的幾種用法

1 鎖方法

public synchronized void dodo(){ }

這個(gè)就是鎖方法,這里面要注意兩點(diǎn):

synchronized 關(guān)鍵子不是方法的一部分,所以它不會被繼承,說白了,就是如果父類的方法有synchronized,子類重寫這個(gè)方法,synchronized不寫也不會報(bào)錯(cuò)

synchronized 不能修飾接口

synchronized 不能修復(fù)構(gòu)造方法,但是可以修飾構(gòu)造方法里面的代碼塊

2 鎖代碼塊

鎖代碼塊就是我上面的那個(gè)例子寫法了,這個(gè)就是鎖的是某個(gè)對象中的某個(gè)代碼,讓它線程同步。  

 synchronized (this) {
                        System.out.print("ThreadName:"+Thread.currentThread().getName()+"  count:"+count+"\n");
                        count++;
 
                    }

我們看到這個(gè)synchronized (this) 里面的this,這里是要傳入一個(gè)對象的,如果不用this也可以,也可以在這個(gè)類里面new一個(gè)其他對象效果也是一樣的,比如

      private Object obj=new Object();
        @Override
        public void run() {
            while (count<15)
            {
                    synchronized (obj)
                    {
                        System.out.print("ThreadName:"+Thread.currentThread().getName()+"  count:"+count+"\n");
                        count++;
                    }
                    try {
                        Thread.sleep(200);
                    }
                    catch (Exception e)
                    {
                    }
            }
        }

這里就用了obj這個(gè)new的對象,效果和this完全一樣

3 鎖某個(gè)類

public class MainClass {
    public static class MyRun implements Runnable
    {
        public static int count=0;
        @Override
        public void run() {
            while (count<15)
            {
                    synchronized (this)
                    {
                       System.out.print("ThreadName:"+Thread.currentThread().getName()+"  count:"+count+"\n");
                        count++;
                    }
                    try {
                        Thread.sleep(200);
                    }
                    catch (Exception e)
                    {
                    }
            }
        }
        public synchronized void dodo()
        {
        }
    }
    public  static void main(String args[])
    {
        MyRun myRun1=new MyRun();
        MyRun myRun2=new MyRun();
        Thread threadA=new Thread(myRun1,"A");
        Thread threadB=new Thread(myRun2,"B");
        threadA.start();
        threadB.start();
    }
}

這個(gè)代碼里面, 

MyRun myRun1=new MyRun();
 MyRun myRun2=new MyRun();

我new兩個(gè)MyRun,我前面說過synchronized(this)只能鎖某個(gè)對象,就是說threadA執(zhí)行myRun1 threadB執(zhí)行myRun2,互不干擾,synchronized只能鎖自己的run1 或者run2 不能兩個(gè)對象同時(shí)鎖到,所以執(zhí)行的結(jié)果是無序的。

ThreadName:A  count:0

ThreadName:B  count:0

ThreadName:B  count:2

ThreadName:A  count:2

ThreadName:B  count:4

ThreadName:A  count:4

ThreadName:A  count:6

ThreadName:B  count:6

ThreadName:A  count:8

ThreadName:B  count:8

如果我們想讓兩個(gè)線程有序執(zhí)行,這個(gè)Count++操作,而且對run1,和run2都同時(shí)鎖,應(yīng)該怎么辦呢???

答案是鎖類,鎖類的意思是不管是這個(gè)類new了多少對象,這個(gè)對象的所有方法,都會上鎖,我們更改下代碼看看結(jié)果,怎么鎖類的:

synchronized (MyRun.class) {
                        System.out.print("ThreadName:"+Thread.currentThread().getName()+"  count:"+count+"\n");
                        count++;
                    }

我們看到只改動了 synchronized (MyRun.class)這里,其他代碼都不變們,這個(gè)就把這個(gè)MyRun鎖了,我們看看結(jié)果:

ThreadName:A  count:0

ThreadName:B  count:1

ThreadName:B  count:2

ThreadName:A  count:3

ThreadName:B  count:4

ThreadName:A  count:5

ThreadName:A  count:6

ThreadName:B  count:7

ThreadName:A  count:8

結(jié)果是有序的,驗(yàn)證了我們的結(jié)果

4 靜態(tài)方法上的synchronized

public synchronized  static void ddo()

這種方式其實(shí)和第三種效果是一樣的,都是對類起作用,因?yàn)槲覀冎纒tatic修飾的方法是類方法,所以這個(gè)synchronized 也是作用于整個(gè)類

我們把上面的代碼改下看看效果是不是一樣:

public class MainClass {
    public static class MyRun implements Runnable
    {
        public static int count=0;
        @Override
        public void run() {
            ddo();
        }
        public synchronized  static void ddo()
        {
            while (count<15)
            {
                    System.out.print("ThreadName:"+Thread.currentThread().getName()+"  count:"+count+"\n");
                    count++;
                try {
                    Thread.sleep(200);
                }
                catch (Exception e)
                {
                }
            }
        }
    }
    public  static void main(String args[])
    {
        MyRun myRun1=new MyRun();
        MyRun myRun2=new MyRun();
        Thread threadA=new Thread(myRun1,"A");
        Thread threadB=new Thread(myRun2,"B");
        threadA.start();
        threadB.start();
    }
}

結(jié)果:

ThreadName:A  count:0

ThreadName:A  count:1

ThreadName:A  count:2

ThreadName:A  count:3

ThreadName:A  count:4

ThreadName:A  count:5

ThreadName:A  count:6

ThreadName:A  count:7

ThreadName:A  count:8

因?yàn)锳線程 先執(zhí)行最后滿足條件 while (count<15),所以B沒有機(jī)會執(zhí)行了,驗(yàn)證符合我們的預(yù)期

總結(jié)

1、鎖如果加在方法上面,或者在方法中的代碼塊形式,就是鎖的這個(gè)對象,如果鎖是靜態(tài)方法中,或者代碼塊synchronized(A.class) 形式 就是鎖的這個(gè)類,里面的所有方法都會同步。

2、誰擁有了鎖,上面線程就擁有了控制這段代碼的能力,其他的線程只能看著,只有釋放了鎖,其他線程才可以操作。

3、synchronized 消耗系統(tǒng)性能,所以能不加鎖的邏輯,盡量不要加。

4、操作讀寫文件,或者數(shù)據(jù)庫,有的時(shí)候多線程會出現(xiàn)不可預(yù)知的問題,所以要加入鎖。

到此這篇關(guān)于Java中synchronized的四種用法詳解的文章就介紹到這了,更多相關(guān)synchronized的用法內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • springboot?Long?精度丟失問題解決

    springboot?Long?精度丟失問題解決

    這篇文章主要為大家介紹了解決springboot?Long?精度丟失問題的方法詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-07-07
  • SpringBoot項(xiàng)目如何訪問jsp頁面的示例代碼

    SpringBoot項(xiàng)目如何訪問jsp頁面的示例代碼

    本篇文章主要介紹了SpringBoot項(xiàng)目如何訪問jsp頁面的示例代碼,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-10-10
  • 如何使用Playwright對Java API實(shí)現(xiàn)自動視覺測試

    如何使用Playwright對Java API實(shí)現(xiàn)自動視覺測試

    這篇文章主要介紹了如何使用Playwright對Java API實(shí)現(xiàn)自動視覺測試,幫助大家更好的理解和使用Playwright,感興趣的朋友可以了解下
    2021-01-01
  • Java中遍歷ConcurrentHashMap的四種方式詳解

    Java中遍歷ConcurrentHashMap的四種方式詳解

    這篇文章主要介紹了Java中遍歷ConcurrentHashMap的四種方式詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-10-10
  • Java利用docx4j+Freemarker生成word文檔

    Java利用docx4j+Freemarker生成word文檔

    這篇文章主要為大家詳細(xì)介紹了Java如何利用docx4j+Freemarker生成word文檔,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2025-04-04
  • java實(shí)現(xiàn)簡易飛機(jī)大戰(zhàn)

    java實(shí)現(xiàn)簡易飛機(jī)大戰(zhàn)

    這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)簡易飛機(jī)大戰(zhàn),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-05-05
  • 創(chuàng)建網(wǎng)關(guān)項(xiàng)目(Spring Cloud Gateway)過程詳解

    創(chuàng)建網(wǎng)關(guān)項(xiàng)目(Spring Cloud Gateway)過程詳解

    這篇文章主要介紹了創(chuàng)建網(wǎng)關(guān)項(xiàng)目(Spring Cloud Gateway)過程詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-09-09
  • java枚舉類的屬性、方法和構(gòu)造方法應(yīng)用實(shí)戰(zhàn)

    java枚舉類的屬性、方法和構(gòu)造方法應(yīng)用實(shí)戰(zhàn)

    這篇文章主要介紹了java枚舉類的屬性、方法和構(gòu)造方法應(yīng)用,結(jié)合實(shí)例形式分析了java枚舉類的定義、構(gòu)造及相關(guān)應(yīng)用操作技巧,需要的朋友可以參考下
    2019-08-08
  • Mybatis攔截器如何實(shí)現(xiàn)數(shù)據(jù)權(quán)限過濾

    Mybatis攔截器如何實(shí)現(xiàn)數(shù)據(jù)權(quán)限過濾

    本文介紹了MyBatis攔截器的使用,通過實(shí)現(xiàn)Interceptor接口對SQL進(jìn)行處理,實(shí)現(xiàn)數(shù)據(jù)權(quán)限過濾功能,通過在本地線程變量中存儲數(shù)據(jù)權(quán)限相關(guān)信息,并在攔截器的intercept方法中進(jìn)行SQL增強(qiáng)處理
    2024-12-12
  • Java 靜態(tài)綁定與動態(tài)綁定深入分析

    Java 靜態(tài)綁定與動態(tài)綁定深入分析

    這篇文章主要介紹了Java 靜態(tài)綁定與動態(tài)綁定深入分析的相關(guān)資料,這里對java 的動態(tài)綁定和靜態(tài)綁定做了詳細(xì)的介紹,對其進(jìn)行總結(jié)整理,需要的朋友可以參考下
    2016-11-11

最新評論