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

Java中synchronized的四種用法詳解

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

問(wèn)題描述

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

下面這個(gè)是一個(gè)測(cè)試?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在無(wú)序的增加,這個(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í)行完這段代碼之后就會(huì)釋放對(duì)這個(gè)對(duì)象的這段代碼的釋放鎖,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í)行,不會(huì)同時(shí)搶占執(zhí)行Count++ 操作,

下面介紹synchronised的幾種用法

1 鎖方法

public synchronized void dodo(){ }

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

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

synchronized 不能修飾接口

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

2 鎖代碼塊

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

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

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

      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的對(duì)象,效果和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,我前面說(shuō)過(guò)synchronized(this)只能鎖某個(gè)對(duì)象,就是說(shuō)threadA執(zhí)行myRun1 threadB執(zhí)行myRun2,互不干擾,synchronized只能鎖自己的run1 或者run2 不能兩個(gè)對(duì)象同時(shí)鎖到,所以執(zhí)行的結(jié)果是無(wú)序的。

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++操作,而且對(duì)run1,和run2都同時(shí)鎖,應(yīng)該怎么辦呢???

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

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

我們看到只改動(dòng)了 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í)和第三種效果是一樣的,都是對(duì)類起作用,因?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ī)會(huì)執(zhí)行了,驗(yàn)證符合我們的預(yù)期

總結(jié)

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

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

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

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

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

相關(guān)文章

最新評(píng)論