国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專(zhuān)欄INFORMATION COLUMN

Java多線程學(xué)習(xí)(二)synchronized關(guān)鍵字(1)

xuxueli / 1723人閱讀

摘要:轉(zhuǎn)載請(qǐng)備注地址多線程學(xué)習(xí)二將分為兩篇文章介紹同步方法另一篇介紹同步語(yǔ)句塊。如果兩個(gè)線程同時(shí)操作對(duì)象中的實(shí)例變量,則會(huì)出現(xiàn)非線程安全,解決辦法就是在方法前加上關(guān)鍵字即可。

轉(zhuǎn)載請(qǐng)備注地址: https://blog.csdn.net/qq_3433...

Java多線程學(xué)習(xí)(二)將分為兩篇文章介紹synchronized同步方法另一篇介紹synchronized同步語(yǔ)句塊
系列文章傳送門(mén):

Java多線程學(xué)習(xí)(一)Java多線程入門(mén)

Java多線程學(xué)習(xí)(二)synchronized關(guān)鍵字(1)

java多線程學(xué)習(xí)(二)synchronized關(guān)鍵字(2)

Java多線程學(xué)習(xí)(三)volatile關(guān)鍵字

Java多線程學(xué)習(xí)(四)等待/通知(wait/notify)機(jī)制

Java多線程學(xué)習(xí)(五)線程間通信知識(shí)點(diǎn)補(bǔ)充

Java多線程學(xué)習(xí)(六)Lock鎖的使用

Java多線程學(xué)習(xí)(七)并發(fā)編程中一些問(wèn)題

系列文章將被優(yōu)先更新與微信公眾號(hào)“Java面試通關(guān)手冊(cè)”,歡迎廣大Java程序員和愛(ài)好技術(shù)的人員關(guān)注。

(1) synchronized同步方法

本節(jié)思維導(dǎo)圖:

思維導(dǎo)圖源文件+思維導(dǎo)圖軟件關(guān)注微信公眾號(hào):“Java面試通關(guān)手冊(cè)”回復(fù)關(guān)鍵字:“Java多線程”免費(fèi)領(lǐng)取。

一 簡(jiǎn)介

Java并發(fā)編程這個(gè)領(lǐng)域中synchronized關(guān)鍵字一直都是元老級(jí)的角色,很久之前很多人都會(huì)稱(chēng)它為“重量級(jí)鎖”。但是,在JavaSE 1.6之后進(jìn)行了主要包括為了減少獲得鎖和釋放鎖帶來(lái)的性能消耗而引入的偏向鎖和輕量級(jí)鎖以及其它各種優(yōu)化之后變得在某些情況下并不是那么重了。

這一篇文章不會(huì)介紹synchronized關(guān)鍵字的實(shí)現(xiàn)原理,更多的是synchronized關(guān)鍵字的使用。如果想要了解的可以看看方騰飛的《Java并發(fā)編程的藝術(shù)》。

二 變量安全性

“非線程安全”問(wèn)題存在于“實(shí)例變量”中,如果是方法內(nèi)部的私有變量,則不存在“非線程安全”問(wèn)題,所得結(jié)果也就是“線程安全”的了。

如果兩個(gè)線程同時(shí)操作對(duì)象中的實(shí)例變量,則會(huì)出現(xiàn)“非線程安全”,解決辦法就是在方法前加上synchronized關(guān)鍵字即可。前面一篇文章我們已經(jīng)講過(guò),而且貼過(guò)相應(yīng)代碼,所以這里就不再貼代碼了。

三 多個(gè)對(duì)象多個(gè)鎖

先看例子:

HasSelfPrivateNum.java

public class HasSelfPrivateNum {

    private int num = 0;

    synchronized public void addI(String username) {
        try {
            if (username.equals("a")) {
                num = 100;
                System.out.println("a set over!");
                //如果去掉hread.sleep(2000),那么運(yùn)行結(jié)果就會(huì)顯示為同步的效果
                Thread.sleep(2000);
            } else {
                num = 200;
                System.out.println("b set over!");
            }
            System.out.println(username + " num=" + num);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

}

ThreadA.java

public class ThreadA extends Thread {

    private HasSelfPrivateNum numRef;

    public ThreadA(HasSelfPrivateNum numRef) {
        super();
        this.numRef = numRef;
    }

    @Override
    public void run() {
        super.run();
        numRef.addI("a");
    }

}

ThreadB.java

public class ThreadB extends Thread {

    private HasSelfPrivateNum numRef;

    public ThreadB(HasSelfPrivateNum numRef) {
        super();
        this.numRef = numRef;
    }

    @Override
    public void run() {
        super.run();
        numRef.addI("b");
    }

}

Run.java

public class Run {

    public static void main(String[] args) {

        HasSelfPrivateNum numRef1 = new HasSelfPrivateNum();
        HasSelfPrivateNum numRef2 = new HasSelfPrivateNum();

        ThreadA athread = new ThreadA(numRef1);
        athread.start();

        ThreadB bthread = new ThreadB(numRef2);
        bthread.start();

    }

}

運(yùn)行結(jié)果:
a num=100停頓一會(huì)才執(zhí)行

上面實(shí)例中兩個(gè)線程ThreadA和ThreadB分別訪問(wèn)同一個(gè)類(lèi)的不同實(shí)例的相同名稱(chēng)的同步方法,但是效果確實(shí)異步執(zhí)行。

為什么會(huì)這樣呢?

這是因?yàn)?font color="red">synchronized取得的鎖都是對(duì)象鎖,而不是把一段代碼或方法當(dāng)做鎖。所以在上面的實(shí)例中,哪個(gè)線程先執(zhí)行帶synchronized關(guān)鍵字的方法,則哪個(gè)線程就持有該方法所屬對(duì)象的鎖Lock,那么其他線程只能呈等待狀態(tài),前提是多個(gè)線程訪問(wèn)的是同一個(gè)對(duì)象。本例中很顯然是兩個(gè)對(duì)象。

在本例中創(chuàng)建了兩個(gè)HasSelfPrivateNum類(lèi)對(duì)象,所以就產(chǎn)生了兩個(gè)鎖。當(dāng)ThreadA的引用執(zhí)行到addI方法中的runThread.sleep(2000)語(yǔ)句時(shí),ThreadB就會(huì)“乘機(jī)執(zhí)行”。所以才會(huì)導(dǎo)致執(zhí)行結(jié)果如上圖所示(備注:由于runThread.sleep(2000),“a num=100”停頓了兩秒才輸出)

四 synchronized方法與鎖對(duì)象

通過(guò)上面我們知道synchronized取得的鎖都是對(duì)象鎖,而不是把一段代碼或方法當(dāng)做鎖。如果多個(gè)線程訪問(wèn)的是同一個(gè)對(duì)象,哪個(gè)線程先執(zhí)行帶synchronized關(guān)鍵字的方法,則哪個(gè)線程就持有該方法,那么其他線程只能呈等待狀態(tài)。如果多個(gè)線程訪問(wèn)的是多個(gè)對(duì)象則不一定,因?yàn)槎鄠€(gè)對(duì)象會(huì)產(chǎn)生多個(gè)鎖。

那么我們思考一下當(dāng)多個(gè)線程訪問(wèn)的是同一個(gè)對(duì)象中的非synchronized類(lèi)型方法會(huì)是什么效果?

答案是:會(huì)異步調(diào)用非synchronized類(lèi)型方法,解決辦法也很簡(jiǎn)單在非synchronized類(lèi)型方法前加上synchronized關(guān)鍵字即可。

五 臟讀

發(fā)生臟讀的情況實(shí)在讀取實(shí)例變量時(shí),此值已經(jīng)被其他線程更改過(guò)。

PublicVar.java

public class PublicVar {

    public String username = "A";
    public String password = "AA";

    synchronized public void setValue(String username, String password) {
        try {
            this.username = username;
            Thread.sleep(5000);
            this.password = password;

            System.out.println("setValue method thread name="
                    + Thread.currentThread().getName() + " username="
                    + username + " password=" + password);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
     //該方法前加上synchronized關(guān)鍵字就同步了
     public void getValue() {
        System.out.println("getValue method thread name="
                + Thread.currentThread().getName() + " username=" + username
                + " password=" + password);
    }
}

ThreadA.java

public class ThreadA extends Thread {

    private PublicVar publicVar;

    public ThreadA(PublicVar publicVar) {
        super();
        this.publicVar = publicVar;
    }

    @Override
    public void run() {
        super.run();
        publicVar.setValue("B", "BB");
    }
}

Test.java

public class Test {

    public static void main(String[] args) {
        try {
            PublicVar publicVarRef = new PublicVar();
            ThreadA thread = new ThreadA(publicVarRef);
            thread.start();

            Thread.sleep(200);//打印結(jié)果受此值大小影響

            publicVarRef.getValue();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }
}

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

解決辦法:getValue()方法前加上synchronized關(guān)鍵字即可。

加上synchronized關(guān)鍵字后的運(yùn)行結(jié)果:

六 synchronized鎖重入

“可重入鎖”概念是:自己可以再次獲取自己的內(nèi)部鎖。比如一個(gè)線程獲得了某個(gè)對(duì)象的鎖,此時(shí)這個(gè)對(duì)象鎖還沒(méi)有釋放,當(dāng)其再次想要獲取這個(gè)對(duì)象的鎖的時(shí)候還是可以獲取的,如果不可鎖重入的話,就會(huì)造成死鎖。

Service.java

public class Service {

    synchronized public void service1() {
        System.out.println("service1");
        service2();
    }

    synchronized public void service2() {
        System.out.println("service2");
        service3();
    }

    synchronized public void service3() {
        System.out.println("service3");
    }

}

MyThread.java

public class MyThread extends Thread {
    @Override
    public void run() {
        Service service = new Service();
        service.service1();
    }

}

Run.java

public class Run {
    public static void main(String[] args) {
        MyThread t = new MyThread();
        t.start();
    }
}

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

另外可重入鎖也支持在父子類(lèi)繼承的環(huán)境中

Main.java:

public class Main {

    public int i = 10;

    synchronized public void operateIMainMethod() {
        try {
            i--;
            System.out.println("main print i=" + i);
            Thread.sleep(100);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

Sub.java:

public class Sub extends Main {

    synchronized public void operateISubMethod() {
        try {
            while (i > 0) {
                i--;
                System.out.println("sub print i=" + i);
                Thread.sleep(100);
                this.operateIMainMethod();
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

MyThread.java:

public class MyThread extends Thread {
    @Override
    public void run() {
        Sub sub = new Sub();
        sub.operateISubMethod();
    }
}

Run.java:

public class Run {
    public static void main(String[] args) {
        MyThread t = new MyThread();
        t.start();
    }
}

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

說(shuō)明當(dāng)存在父子類(lèi)繼承關(guān)系時(shí),子類(lèi)是完全可以通過(guò)“可重入鎖”調(diào)用父類(lèi)的同步方法。

另外出現(xiàn)異常時(shí),其鎖持有的鎖會(huì)自動(dòng)釋放。

七 同步不具有繼承性

如果父類(lèi)有一個(gè)帶synchronized關(guān)鍵字的方法,子類(lèi)繼承并重寫(xiě)了這個(gè)方法。
但是同步不能繼承,所以還是需要在子類(lèi)方法中添加synchronized關(guān)鍵字。

參考:
《Java多線程編程核心技術(shù)》

歡迎關(guān)注我的微信公眾號(hào):"Java面試通關(guān)手冊(cè)"(分享各種Java學(xué)習(xí)資源,面試題,以及企業(yè)級(jí)Java實(shí)戰(zhàn)項(xiàng)目回復(fù)關(guān)鍵字免費(fèi)領(lǐng)取):

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/69103.html

相關(guān)文章

  • Java線程學(xué)習(xí)synchronized關(guān)鍵字(2)

    摘要:關(guān)鍵字加到非靜態(tài)方法上持有的是對(duì)象鎖。線程和線程持有的鎖不一樣,所以和運(yùn)行同步,但是和運(yùn)行不同步。所以盡量不要使用而使用參考多線程編程核心技術(shù)并發(fā)編程的藝術(shù)如果你覺(jué)得博主的文章不錯(cuò),歡迎轉(zhuǎn)發(fā)點(diǎn)贊。 系列文章傳送門(mén): Java多線程學(xué)習(xí)(一)Java多線程入門(mén) Java多線程學(xué)習(xí)(二)synchronized關(guān)鍵字(1) java多線程學(xué)習(xí)(二)synchronized關(guān)鍵字(2) J...

    Batkid 評(píng)論0 收藏0
  • Java線程學(xué)習(xí)(四)等待/通知(wait/notify)機(jī)制

    摘要:運(yùn)行可運(yùn)行狀態(tài)的線程獲得了時(shí)間片,執(zhí)行程序代碼。阻塞的情況分三種一等待阻塞運(yùn)行的線程執(zhí)行方法,會(huì)把該線程放入等待隊(duì)列中。死亡線程方法執(zhí)行結(jié)束,或者因異常退出了方法,則該線程結(jié)束生命周期。死亡的線程不可再次復(fù)生。 系列文章傳送門(mén): Java多線程學(xué)習(xí)(一)Java多線程入門(mén) Java多線程學(xué)習(xí)(二)synchronized關(guān)鍵字(1) java多線程學(xué)習(xí)(二)synchronized關(guān)鍵...

    PiscesYE 評(píng)論0 收藏0
  • Java線程學(xué)習(xí)(三)volatile關(guān)鍵字

    摘要:三關(guān)鍵字能保證原子性嗎并發(fā)編程藝術(shù)這本書(shū)上說(shuō)保證但是在自增操作非原子操作上不保證,多線程編程核心藝術(shù)這本書(shū)說(shuō)不保證。多線程訪問(wèn)關(guān)鍵字不會(huì)發(fā)生阻塞,而關(guān)鍵字可能會(huì)發(fā)生阻塞關(guān)鍵字能保證數(shù)據(jù)的可見(jiàn)性,但不能保證數(shù)據(jù)的原子性。 系列文章傳送門(mén): Java多線程學(xué)習(xí)(一)Java多線程入門(mén) Java多線程學(xué)習(xí)(二)synchronized關(guān)鍵字(1) java多線程學(xué)習(xí)(二)synchroniz...

    tain335 評(píng)論0 收藏0
  • 線程學(xué)習(xí)筆記(1):volatile和synchronized

    摘要:今天開(kāi)始整理學(xué)習(xí)多線程的知識(shí),談?wù)勛钪匾膬蓚€(gè)關(guān)鍵字和。但是這樣一個(gè)過(guò)程比較慢,在使用多線程的時(shí)候就會(huì)出現(xiàn)問(wèn)題。有序性有序性是指多線程執(zhí)行結(jié)果的正確性。這種機(jī)制在多線程中會(huì)出現(xiàn)問(wèn)題,因此可以通過(guò)來(lái)禁止重排。 今天開(kāi)始整理學(xué)習(xí)多線程的知識(shí),談?wù)勛钪匾膬蓚€(gè)關(guān)鍵字:volatile和synchronized。 一、三個(gè)特性 1、原子性 所謂原子性操作就是指這些操作是不可中斷的,要么執(zhí)行過(guò)程...

    jk_v1 評(píng)論0 收藏0
  • 值得保存的 synchronized 關(guān)鍵字總結(jié)

    摘要:無(wú)論是互斥鎖,還是自旋鎖,在任何時(shí)刻,最多只能有一個(gè)保持者,也就說(shuō),在任何時(shí)刻最多只能有一個(gè)執(zhí)行單元獲得鎖。另外在中引入了自適應(yīng)的自旋鎖。和關(guān)鍵字的總結(jié)推薦一 該文已加入開(kāi)源文檔:JavaGuide(一份涵蓋大部分Java程序員所需要掌握的核心知識(shí))。地址:https://github.com/Snailclimb... 本文是對(duì) synchronized 關(guān)鍵字使用、底層原理、JD...

    miguel.jiang 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<