日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

你用或者不用:线程中synchronized关键字使用总结

發(fā)布時(shí)間:2024/2/28 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 你用或者不用:线程中synchronized关键字使用总结 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.


感謝張龍老師!

Synchronized關(guān)鍵字,同步的, synchronized關(guān)鍵字可以修飾方法,還有靜態(tài)代碼塊(static block)

Java中的每一個(gè)對(duì)象都有一把鎖(lock),只是平時(shí)狀態(tài)下,鎖是開著的,當(dāng)被synchronized關(guān)鍵字所修飾時(shí),就將這把鎖激活,當(dāng)一個(gè)對(duì)象被多個(gè)線程所調(diào)用時(shí),由于線程的行進(jìn)度的不確定性,可能會(huì)引發(fā)方法內(nèi)很多問題,而synchronized關(guān)鍵字就是只允許方法每一次只能允許一個(gè)線程訪問,只有當(dāng)線程訪問結(jié)束,或者拋出異常時(shí),才允許下一個(gè)線程的介入:

(張龍老師的文檔說的很清楚了,這點(diǎn)也是非常重要的)

模擬銀行取錢系統(tǒng):

/*

?* 在這個(gè)程序中我遇到了一個(gè)問題

?* 就是為什么要在類中定義一個(gè)其他類的成員變量

?* 我一開始是new出來的,發(fā)現(xiàn)這樣做很不應(yīng)該

?* 特別是在線程中,這樣做是一點(diǎn)都體現(xiàn)不了線程的作用;

?* 這樣做的話,每一次調(diào)用啟用類都會(huì)生成調(diào)用類的對(duì)象;相當(dāng)于是線程之間不會(huì)影響;

?* 而定義成員類,不管生成多少個(gè)啟用類,都可以只傳入一個(gè)調(diào)用類;

?*/

?

package thread;

?

publicclass FetchMoneyTest

{

?? publicstaticvoid main(String[] args)

?? {

????? Bank bank = new Bank();

????? ThreadDemo test1 = new ThreadDemo(bank);

????? ThreadDemo test2 = new ThreadDemo(bank);

????? test1.start();

????? test2.start();

?? }

}

?

class Bank

{

?? publicintmoney = 1000;

?

?? public?int getMoney(int number)throwsInterruptedException

?? {

????? if (number < 0)

????? {

??????? return -1;

?

????? }

????? elseif (number > 1000)

????? {

??????? return -2;

????? }

????? else

????? {

??????? Thread.sleep(1200);

??????? money -= number;

??????? System.out.println(money);

???????

??????? return number;

????? }

?

?? }

?

}

?

class ThreadDemoextends Thread

{

?? private Bankbank;

?? public ThreadDemo(Bank bank)

?? {

????? this.bank = bank;

?? }

?? @Override

?? publicvoid run()

?? {

?????

????? try

????? {

??????? System.out.println(bank.getMoney(800));

????? }

????? catch (InterruptedException e)

????? {

??????? // TODO Auto-generatedcatch block

??????? e.printStackTrace();

????? }

?? }

}

?

下面的程序只改變一點(diǎn),就是只加上synchronized關(guān)鍵字:

/*

?* 在這個(gè)程序中我遇到了一個(gè)問題

?* 就是為什么要在類中定義一個(gè)其他類的成員變量

?* 我一開始是new出來的,發(fā)現(xiàn)這樣做很不應(yīng)該

?* 特別是在線程中,這樣做是一點(diǎn)都體現(xiàn)不了線程的作用;

?* 這樣做的話,每一次調(diào)用啟用類都會(huì)生成調(diào)用類的對(duì)象;相當(dāng)于是線程之間不會(huì)影響;

?* 而定義成員類,不管生成多少個(gè)啟用類,都可以只傳入一個(gè)調(diào)用類;

?*/

?

package thread;

?

publicclass FetchMoneyTest

{

?? publicstaticvoid main(String[] args)

?? {

????? Bank bank = new Bank();

????? ThreadDemo test1 = new ThreadDemo(bank);

????? ThreadDemo test2 = new ThreadDemo(bank);

????? test1.start();

????? test2.start();

?? }

}

?

class Bank

{

?? publicintmoney = 1000;

?

?? publicsynchronizedint getMoney(int number)throws InterruptedException

?? //加上了synchronized關(guān)鍵字后,線程將會(huì)卓一的通過這個(gè)方法,第二次的時(shí)候顯然不符合方法的第三個(gè)約定,返回-3

?? {

????? if (number < 0)

????? {

??????? return -1;

?

????? }

????? elseif (number > 1000)

????? {

??????? return -2;

????? }

????? elseif(money < number)

????? {

??????? return -3;

????? }

????? else

????? {

??????? Thread.sleep(1200);

??????? money -= number;

??????? System.out.println(money);

???????

??????? return number;

????? }

?

?? }

?

}

?

class ThreadDemoextends Thread

{

?? private Bankbank;

?? public ThreadDemo(Bank bank)

?? {

????? this.bank = bank;

?? }

?? @Override

?? publicvoid run()

?? {

?????

????? try

????? {

??????? System.out.println(bank.getMoney(800));

????? }

????? catch (InterruptedException e)

????? {

??????? // TODO Auto-generatedcatch block

??????? e.printStackTrace();

????? }

?? }

}

?

??

25.

人是不能夠懶得,我應(yīng)該有自己的一套,下面來深度的理解張龍老師說的一句話,被synchronized修飾方法的對(duì)象會(huì)上鎖,如果一個(gè)類的多個(gè)方法都被synchronized修飾時(shí),當(dāng)一個(gè)線程未訪問完畢其中的一個(gè)synchronized方法時(shí),其他的線程是不能訪問任何該對(duì)象的任何一個(gè)synchronized方法的,除非你生成了兩個(gè)對(duì)象!

下面我們來一步步的分析:

首先 當(dāng)一個(gè)類中的兩個(gè)方法都沒有被synchronized修飾時(shí),這兩個(gè)方法的打印將是隨機(jī)進(jìn)行的:

package thread;

?

publicclass ThreadTest10

{

?? publicstaticvoid main(String[] args)

?? {

????? Demo demo1 = new Demo();

????? ThreadTest11 test1 = new ThreadTest11(demo1);

????? ThreadTest12 test2 = new ThreadTest12(demo1);

????? test1.start();

????? test2.start();

?? }

}

class Demo

{

?? publicvoid method1()throws InterruptedException

?? {

????? for(int i = 0 ; i < 15 ; i ++)

????? {

??????? Thread.sleep((long)(Math.random()*1000));

??????? System.out.println("hello:"+ i );

????? }

?? }

?? publicvoid method2()throws InterruptedException

?? {

?????

????? for(int i = 0 ; i < 15; i ++)

????? {

??????? Thread.sleep((long)(Math.random()*1000));

??????? System.out.println("world:"+i);

???????

????? }

?? }

}

class ThreadTest11extends Thread

{

?? private Demodemo;

?? public ThreadTest11 (Demo demo)

?? {

????? this.demo = demo;

?? }

?? @Override

?? publicvoid run()

?? {

????? try

????? {

??????? demo.method1();

????? }

????? catch (InterruptedException e)

????? {

??????? // TODO Auto-generatedcatch block

??????? e.printStackTrace();

????? }

?? }

??

??

}

class ThreadTest12extends Thread

{

?? private Demodemo;

?? public ThreadTest12 (Demo demo)

?? {

????? this.demo = demo;

?? }

?? @Override

?? publicvoid run()

?? {

????? try

????? {

??????? demo.method2();

????? }

????? catch (InterruptedException e)

????? {

??????? // TODO Auto-generatedcatch block

?? ????? e.printStackTrace();

????? }

?? }

??

??

}

?

?

?

?

現(xiàn)在我要為上面的兩個(gè)方法加上synchronized關(guān)鍵字,使之變得有序,如果只加上一個(gè)的話,是沒有意義的,還是亂序,因?yàn)橥椒椒?#xff0c;可以和非同步方法同時(shí)運(yùn)行;

加上后將會(huì)輸出有序;先輸出hello 或者 world;

?

?

下面

說過 synchronized只修飾一個(gè)對(duì)象,如果我傳入的是兩個(gè)對(duì)象,即使加上了synchronized關(guān)鍵字,它們也不會(huì)互相影響;

更改如下:

publicstaticvoid main(String[] args)

?? {

????? Demodemo1 = new Demo();

????? ThreadTest11 test1 = new ThreadTest11(demo1);

????? demo1 = newDemo();

????? ThreadTest12 test2 = new ThreadTest12(demo1);

????? test1.start();

????? test2.start();

?? }

?

?

下面將是講述的重點(diǎn),就是關(guān)鍵字synchronized 與static合用的效果,我們知道,不管一個(gè)類生成多少個(gè)對(duì)象,這些對(duì)象實(shí)例都只有一個(gè)共同的類,synchronized只能鎖住一個(gè)類的對(duì)象,而被 synchronizedstatic修飾的方法,將會(huì)鎖住對(duì)象的類!!,即不管你生成多少個(gè)類的對(duì)象,我們都相當(dāng)于你調(diào)用的是同一個(gè)對(duì)象;所以上面的輸出將會(huì)變得有序!

package thread;

?

publicclass ThreadTest10

{

?? publicstaticvoid main(String[] args)

?? {

????? Demo demo1 = new Demo();

????? ThreadTest11 test1 = new ThreadTest11(demo1);

????? demo1 = new Demo();

????? ThreadTest12 test2 = new ThreadTest12(demo1);

????? test1.start();

????? test2.start();

?? }

}

class Demo

{

?? publicsynchronizedstaticvoid method1()throws InterruptedException

?? {

????? for(int i = 0 ; i < 15 ; i ++)

????? {

??????? Thread.sleep((long)(Math.random()*1000));

??????? System.out.println("hello:"+ i );

????? }

?? }

?? publicsynchronizedstaticvoid method2()throwsInterruptedException

?? {

?????

????? for(int i = 0 ; i < 15; i ++)

????? {

??????? Thread.sleep((long)(Math.random()*1000));

??????? System.out.println("world:"+i);

???????

????? }

?? }

}

class ThreadTest11extends Thread

{

?? private Demodemo;

?? public ThreadTest11 (Demo demo)

?? {

????? this.demo = demo;

?? }

?? @Override

?? publicvoid run()

?? {

????? try

????? {

??????? demo.method1();

????? }

????? catch (InterruptedException e)

????? {

??????? // TODO Auto-generatedcatch block

??????? e.printStackTrace();

????? }

?? }

??

??

}

class ThreadTest12extends Thread

{

?? private Demodemo;

?? public ThreadTest12 (Demo demo)

?? {

????? this.demo = demo;

?? }

?? @Override

?? publicvoid run()

?? {

????? try

????? {

??????? demo.method2();

????? }

????? catch (InterruptedException e)

????? {

??????? // TODO Auto-generatedcatch block

??????? e.printStackTrace();

????? }

?? }

??

}

?

?

?

?

26.

下面介紹synchronized代碼塊,個(gè)人以為,重要度遠(yuǎn)遠(yuǎn)高于單純的修飾synchronized方法:

一方面:高效率!

另一方面:后面涉及到的wait和notify方法,都要涉及

Synchronized要修飾一個(gè)對(duì)象

即:synchronized(Object);

表示將對(duì)象object上鎖,這里的object對(duì)象其實(shí)是沒有用的,只是說明被上鎖,個(gè)人建議使用this關(guān)鍵字,表示將當(dāng)前對(duì)象上鎖!

看下面的synchronized代碼塊代碼同樣實(shí)現(xiàn)了兩個(gè)方法的順序執(zhí)行:

?

?

?

package thread;

?

publicclass BlockTest

{

?? publicstaticvoid main(String[] args)

?? {

????? Block block = new Block();

????? ThreadTestX test1 = new ThreadTestX(block);

????? ThreadTestXX test2 = new ThreadTestXX(block);

????? test1.start();

????? test2.start();

?? }

}

class Block

{

?? publicvoid method1()

?? {

????? synchronized (this)

????? {

??????? for(int i = 0; i < 15; i++)

??????? {

?????????? System.out.println("hello :"+ i);

??????????

??????? ??

??????? }

????? }

?? }

?? publicvoid method2()

?? {

????? synchronized(this)

????? {

??????? for(int i = 0 ; i <15; i ++)

??????? {

?????????? System.out.println("world!"+ i);

??????????

??????? }

????? }

?? }

}

class ThreadTestXextends Thread

{

?? private Blockblock;

?? public ThreadTestX(Block block)

?? {

????? this.block = block;

?? }

?? @Override

?? publicvoid run()

?? {

????? block.method1();

?? }

??

}

class ThreadTestXXextends Thread

{

?? private Blockblock;

?? public ThreadTestXX(Block block)

?? {

????? this.block = block;

?? }

?? @Override

?? publicvoid run()

?? {

????? block.method2();

?? }

??

}

?

?


總結(jié)

以上是生活随笔為你收集整理的你用或者不用:线程中synchronized关键字使用总结的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。