麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

首頁(yè) > 學(xué)院 > 開(kāi)發(fā)設(shè)計(jì) > 正文

java筆記六:線程間的協(xié)調(diào)

2019-11-17 03:27:30
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

  昨天重新學(xué)習(xí)了java多線程的使用,多線程的難點(diǎn)就在線程之間的協(xié)調(diào)。在《操作系統(tǒng)》一課中,我們學(xué)習(xí)了進(jìn)程,其實(shí)多線程和多進(jìn)程一樣,都會(huì)涉及到多個(gè)進(jìn)程或者線程對(duì)某一資源共享訪問(wèn)的問(wèn)題,當(dāng)多個(gè)線程都需要修改這個(gè)資源的時(shí)候就會(huì)出現(xiàn)線程安全問(wèn)題。

  比如說(shuō)在銀行開(kāi)個(gè)賬戶會(huì)有一個(gè)存折和一張卡,如果某一天同一時(shí)間丈夫拿著存折去柜臺(tái)取錢,而妻子拿著銀行卡去ATM取錢。當(dāng)丈夫查詢余額里面有3000元,正準(zhǔn)備取2000元,這時(shí)候妻子也到ATM里面查詢也有3000,也取2000元。其實(shí)銀行不可能讓我們這么做,如果這樣的話那我們天天取錢去了,還搞什么工作啊。其實(shí)在丈夫查詢的時(shí)候已經(jīng)對(duì)該賬號(hào)上了鎖,另外的銀行卡要取錢的話必須等待該鎖被釋放。下面用一個(gè)程序模擬這個(gè)例子:


 1 package com.sync;
 2
 3 public class TestSync2 implements Runnable{
 4     public BankCard bc = new BankCard();
 5     public static void main(String[] args) {
 6         TestSync2 test = new TestSync2();
 7         Thread wife = new Thread(test);
 8         Thread husband = new Thread(test); 
 9         wife.setName("wife");
10         husband.setName("husband");
11         wife.start();
12         husband.start();
13     }
14     public void run() {
15         bc.getMoney(Thread.currentThread().getName(), 2000);
16     }
17 }
18 class BankCard{
19     PRivate static int money = 3000;//模擬賬戶余額
20     public synchronized void getMoney(String name,int m){
21         //synchronized(this){
22             try {
23                 Thread.sleep(1);
24             } catch (InterruptedException e) {
25                 e.printStackTrace();
26             }
27             if(money > m){
28                 System.out.println(name+"取走了"+m+"元");
29                 money = money - m;
30             }else{
31                 System.out.println("對(duì)不起,您的余額不足!");
32             }
33         //}
34     }
35 }

  

  上面的例子如果在getMoney()方法上面不加synchronized關(guān)鍵字的話,輸出結(jié)果為:

wife取走了2000元
husband取走了2000元

  而加上synchronized后,輸出結(jié)果為:

wife取走了2000元
對(duì)不起,您的余額不足!

  上面兩種情況說(shuō)明,如果多個(gè)線程同時(shí)訪問(wèn)某個(gè)資源,而不給該資源枷鎖的話,就會(huì)出現(xiàn)問(wèn)題。而加上synchronized關(guān)鍵字后就可以避免這種錯(cuò)誤發(fā)生了。它能夠保證只有一個(gè)線程能夠訪問(wèn)getMoney()這個(gè)方法,其他藥訪問(wèn)該方法的線程必須等待。

鎖住某個(gè)資源可以用synchronized關(guān)鍵字來(lái)修飾一個(gè)方法或者同步代碼塊,這樣能保證同一時(shí)間只能由一個(gè)線程訪問(wèn)該資源。

    ①、當(dāng)兩個(gè)并發(fā)線程訪問(wèn)同一個(gè)對(duì)象object中的這個(gè)synchronized(this)同步代碼塊時(shí),一個(gè)時(shí)間內(nèi)只能有一個(gè)線程得到執(zhí)行。另一個(gè)線程必須等待當(dāng)前線程執(zhí)行完這個(gè)代碼塊以后才能執(zhí)行該代碼塊。

      ②、然而,當(dāng)一個(gè)線程訪問(wèn)object的一個(gè)synchronized(this)同步代碼塊時(shí),另一個(gè)線程仍然可以訪問(wèn)該object中的非synchronized(this)同步代碼塊。

        ③、尤其關(guān)鍵的是,當(dāng)一個(gè)線程訪問(wèn)object的一個(gè)synchronized(this)同步代碼塊時(shí),其他線程對(duì)object中所有其它synchronized(this)同步代碼塊的訪問(wèn)將被阻塞。

  我們都知道,操作系統(tǒng)中多個(gè)進(jìn)程之間如果不進(jìn)行協(xié)調(diào)就很容易出現(xiàn)死鎖的情況,死鎖的四個(gè)條件:互斥、占有等待、非剝奪、循環(huán)等待。我們只要破壞其中一個(gè)條件就能避免死鎖發(fā)生。線程之間也容易出現(xiàn)死鎖,下面這個(gè)例子就演示了死鎖的情況:


 1 package com.sync;
 2
 3 import com.thread.SleepTest;
 4
 5
 6 public class TestDeadLock implements Runnable{
 7     int flag = 1;
 8     static Object o1 = new Object();
 9     static Object o2 = new Object();
10     public void run() {
11         System.out.println(flag);
12         if(flag == 1){
13             synchronized (o1) {
14                 try {
15                     Thread.sleep(1000);
16                 } catch (InterruptedException e) {
17                     e.printStackTrace();
18                 }
19                 synchronized (o2) {
20                     System.out.println("1");
21                 }
22             }
23         }
24         if(flag == 0){
25             synchronized (o2) {//鎖住某個(gè)對(duì)象,相當(dāng)于占有該對(duì)象不讓其他人使用
26                 try {
27                     Thread.sleep(1000);
28                 } catch (InterruptedException e) {
29                     e.printStackTrace();
30                 }
31                 synchronized (o1) {
32                     System.out.println("0");
33                 }
34             }
35         }
36     }
37     public static void main(String[] args) {
38         TestDeadLock t1 = new TestDeadLock();
39         TestDeadLock t2 = new TestDeadLock();
40         t1.flag = 1;
41         t2.flag = 0;
42         new Thread(t1).start();
43         new Thread(t2).start();
44     }
45 }

  運(yùn)行程序輸出1    0后就進(jìn)入死鎖狀態(tài),該程序永遠(yuǎn)也不會(huì)停止,因?yàn)閮蓚€(gè)線程同時(shí)處于等待狀態(tài)。線程t1鎖住了o1對(duì)象,等待o2對(duì)象,而線程t2鎖住o2等待o2對(duì)象,誰(shuí)也不讓誰(shuí),這就進(jìn)入了一個(gè)循環(huán)占有等待的情況了,死鎖也就出現(xiàn)了。

  所以,如果多個(gè)線程如果不進(jìn)行協(xié)調(diào)的話很容易出現(xiàn)死鎖的問(wèn)題。操作系統(tǒng)中使用進(jìn)程調(diào)度來(lái)協(xié)調(diào)各個(gè)進(jìn)程,那么java重如何對(duì)各個(gè)線程進(jìn)行協(xié)調(diào)呢?

  java中主要使用Object類中的wait()、notify()、notifyAll()方法來(lái)協(xié)調(diào)各個(gè)線程。典型的例子有哲學(xué)家吃飯問(wèn)題、生產(chǎn)者和消費(fèi)者問(wèn)題、理發(fā)師問(wèn)題。下面一個(gè)用一個(gè)例子來(lái)演示生產(chǎn)者和消費(fèi)者問(wèn)題。

  問(wèn)題描述:生產(chǎn)者負(fù)責(zé)做饅頭,做好饅頭后放進(jìn)指定的簍子里面,消費(fèi)者消費(fèi)該簍子里面的饅頭。簍子里只能裝一定量的饅頭,滿了以后生產(chǎn)者必須進(jìn)入等待狀態(tài),消費(fèi)者吃完饅頭后也必須進(jìn)入等待狀態(tài)。


 1 package com.sync;
 2
 3 public class ProductAndConsumer {
 4     public static void main(String[] args) {
 5         Basket b = new Basket();
 6         Product p = new Product(b);
 7         Consumer c = new Consumer(b);
 8         new Thread(p).start();
 9         new Thread(c).start();
10     }
11 }
12
13 class ManTou{
14     int id;
15     public ManTou(int id) {
16         this.id = id;
17     }
18     @Override
19     public String toString() {
20         return "ManTou"+id;
21     }
22 }
23
24 //裝饅頭的籃子
25 class Basket{
26     int index = 0; //相當(dāng)于棧頂指針
27     ManTou[] manTous = new ManTou[6];
28     //往籃子里面放饅頭
29     public synchronized void push(ManTou m){
30         while(index == manTous.length){
31             try {
32                 this.wait();
33             } catch (InterruptedException e) {
34                 e.printStackTrace();
35             }
36         }
37         this.notify();
38         manTous[index] = m;
39         index++;
40     }
41     //往籃子里面取饅頭
42     public synchronized ManTou pop(){
43         while(index == 0){
44             try {
45                 this.wait();
46             } catch (InterruptedException e) {
47                 e.printStackTrace();
48             }
49         }
50         this.notify();
51         index--;
52         return manTous[index];
53     }
54 }
55 //生產(chǎn)者
56 class Product implements Runnable{
57     Basket basket;
58     public Product(Basket basket) {
59         this.basket = basket;
60     }
61     public void run() {
62         for (int i = 0; i < 20; i++) {
63             ManTou m = new ManTou(i);
64             basket.push(m);
65             System.out.println("生產(chǎn)了"+m);
66             try {
67                 Thread.sleep(1);
68             } catch (InterruptedException e) {
69                 e.printStackTrace();
70             }
71            
72         }
73     }
74 }
75
76 //消費(fèi)者
77 class Consumer implements Runnable{
78     Basket basket;
79     public Consumer(Basket basket) {
80         this.basket = basket;
81     }
82     public void run() {
83         for (int i = 0; i < 20; i++) {
84             ManTou m = basket.pop();
85             System.out.println("消費(fèi)了"+m);
86             try {
87                 Thread.sleep((int)(Math.random()*1000));
88             } catch (InterruptedException e) {
89                 e.printStackTrace();
90             }
91         }
92     }
93 }

  wait()、notify()、notifyAll()方法的作用:

    wait():導(dǎo)致當(dāng)前的線程等待,直到其他線程調(diào)用此對(duì)象的 notify() 方法或 notifyAll() 方法。

    notify():喚醒在此對(duì)象監(jiān)視器上等待的單個(gè)線程。

    notifyAll():喚醒在此對(duì)象監(jiān)視器上等待的所有線程。

  wait()與sleep()的區(qū)別:

    兩個(gè)方法的共同點(diǎn)就是讓當(dāng)前線程進(jìn)入等待狀態(tài)。

    不同點(diǎn):

    wait()之后,鎖就不歸我所有了,必須等醒過(guò)來(lái)后才能擁有該鎖,并且必須要有人喚醒它才會(huì)醒過(guò)來(lái)
    sleep()不同,鎖還是歸我所有,一段時(shí)間后會(huì)自動(dòng)醒過(guò)來(lái)


發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 黄色久 | 性爱视频免费 | 国产一区网址 | 一区在线视频 | 嗯~啊~弄嗯~啊h高潮视频 | 日本一区视频在线观看 | 伊人亚洲精品 | 亚洲精久久| 午夜视频免费在线观看 | 国产毛毛片一区二区三区四区 | 中文字幕在线网站 | 免费黄色在线观看网站 | 91网站免费在线观看 | 精品一区二区久久久久久按摩 | 日韩精品久久久 | 蜜桃精品视频 | 蜜桃欧美性大片免费视频 | 亚洲精品久久久久久 | 媚药按摩痉挛w中文字幕 | 国产精品视频 | 国产在线欧美日韩 | 免费在线观看毛片 | 免费一级特黄毛片视频 | 成人羞羞在线观看网站 | 青青草国产在线视频 | 久久久久9999| 黄色片免费看网站 | 色交视频 | 欧美一区二区三区不卡免费观看 | 草莓福利视频在线观看 | 久久国产乱子伦精品 | 久久精品久 | 久久久在线 | 香蕉视频18 | 狠狠色噜噜狠狠狠米奇9999 | 午夜视频在线免费观看 | 色播亚洲| 国产一区二区三区手机在线 | 久久99国产精品免费网站 | 国产91丝袜在线播放 | 在线成人www免费观看视频 |