亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Java多線(xiàn)程之哲學(xué)家就餐問(wèn)題詳解

 更新時(shí)間:2021年04月25日 14:29:27   作者:Dreamchaser追夢(mèng)  
這篇文章主要介紹了Java多線(xiàn)程之哲學(xué)家就餐問(wèn)題詳解,文中有非常詳細(xì)的代碼示例,對(duì)正在學(xué)習(xí)java的小伙伴們有非常好的幫助,需要的朋友可以參考下

一、題目

教材提供一個(gè)哲學(xué)家就餐問(wèn)題的解決方案的框架。本問(wèn)題要求通過(guò)pthreads 互斥鎖來(lái)實(shí)現(xiàn)這個(gè)解決方案。
哲學(xué)家 首先創(chuàng)建 5 個(gè)哲學(xué)家,每個(gè)用數(shù)字 0~4 來(lái)標(biāo)識(shí)。每個(gè)哲學(xué)家作為一個(gè)單獨(dú)的 線(xiàn)程運(yùn)行。 可使用 Pthreads 創(chuàng)建線(xiàn)程。哲學(xué)家在思考和吃飯之間交替。為了模擬這兩種活動(dòng),請(qǐng)讓線(xiàn)程休眠 1 到 3 秒鐘。當(dāng)哲學(xué)家想要吃飯時(shí),他調(diào)用函數(shù):
pickup_forks(int philosopher _number) 其中,philosopher _number
為想吃飯哲學(xué)家的數(shù)字。當(dāng)哲學(xué)家吃完后,他調(diào)用函數(shù):

return _forks(int philosopher _number)

Pthreads 條件變量 Pthreads 條件變量使用數(shù)據(jù)類(lèi)型 pthread_cond_t,采用函數(shù) pthread cond
init()初始化。以下代碼創(chuàng)建并初始化條件變量及其關(guān)聯(lián)的互斥鎖:

pthread _mutex_ t mutex;
pthread_ cond_ t cond _var;
pthread _mutex_ init(&mutex,NULL);
pthread _cond_ init(&cond _var,NULL);

函數(shù) pthread_cond_wait()用于等待條件變量。下面的代碼采用 Pthreads條件變量,說(shuō)明線(xiàn)程如何等待條件 a==b 變?yōu)?br /> true。

pthread _mutex_ lock(&mutex);
while (a != b)
pthread_cond _wait(&mutex, &cond var);
pthread _mutex_ unlock(&mutex);

與條件變量關(guān)聯(lián)的互斥鎖在調(diào)用pthread_cond_wait()函數(shù)之前,應(yīng)加鎖,因?yàn)楸Wo(hù)條件語(yǔ)句中的數(shù)據(jù),避免競(jìng)爭(zhēng)條件。一旦獲得鎖,線(xiàn)程可以檢查條件。如果條件不成立,然后線(xiàn)程調(diào)用 pthread_cond_wait(),傳遞互斥鎖和條件變量作為參數(shù)。調(diào)用pthread_cond_wait()釋放互斥鎖,從而允許另一個(gè)線(xiàn)程訪問(wèn)共享變量,也可更新其值,以便條件語(yǔ)句的計(jì)算結(jié)果為真。(為了防止程序錯(cuò)誤,重要的是將條件語(yǔ)句放在循環(huán)中,以便在被喚醒后重新檢查條件。)修改共享數(shù)據(jù)的線(xiàn)程可以調(diào)用 pthread_cond_signal()函數(shù),從而喚醒一個(gè)等待條件變量的線(xiàn)程。這個(gè)代碼如下:

pthread_ mutex_ lock(&mutex);
a = b;
pthread_ cond_ signal(&cond var);
pthread _mutex_ unlock(&mutex);

需要注意的是,調(diào)用pthread_cond_signal()不會(huì)釋放互斥鎖。隨后調(diào)用pthread_mutex_unlock()釋放互斥鎖。一旦互斥鎖被釋放,喚醒線(xiàn)程成為互斥鎖的所有者,并將控制權(quán)返回到對(duì)pthread cond wait()的調(diào)用。

二、題目解析

題目是書(shū)上的哲學(xué)家就餐問(wèn)題,要求用互斥鎖解決。
這題的關(guān)鍵在于筷子這個(gè)資源的合理使用,書(shū)上給出了三種不同的解決思路:

在這里插入圖片描述

其實(shí)三種方法的核心就是為了解決死鎖問(wèn)題。

什么是死鎖呢?

用專(zhuān)業(yè)點(diǎn)的話(huà)說(shuō)就是:一組互相競(jìng)爭(zhēng)資源的線(xiàn)程因互相等待,導(dǎo)致“永久”阻塞的現(xiàn)象

說(shuō)白了,就是你拿了我想要拿的資源,我拿了你想要拿的資源,而雙方各執(zhí)一詞,導(dǎo)致一直無(wú)法解決問(wèn)題。

那我的思路就是:

雙方各退一步,當(dāng)發(fā)現(xiàn)我想要的資源不夠我完成我所需的事情時(shí),那就把之前拿到的資源放回。這樣就不會(huì)導(dǎo)致雙方互相等待導(dǎo)致死鎖的情況。

當(dāng)然思路不止一種,在極客時(shí)間的Java并發(fā)編程實(shí)戰(zhàn)中有講到死鎖發(fā)生的條件:

只有以下這四個(gè)條件都發(fā)生時(shí)才會(huì)出現(xiàn)死鎖:

互斥,共享資源 X 和 Y 只能被一個(gè)線(xiàn)程占用;占有且等待,線(xiàn)程 T1 已經(jīng)取得共享資源 X,在等待共享資源 Y 的時(shí)候,不釋放共享資源 X;不可搶占,其他線(xiàn)程不能強(qiáng)行搶占線(xiàn)程 T1 占有的資源;循環(huán)等待,線(xiàn)程 T1 等待線(xiàn)程 T2 占有的資源,線(xiàn)程 T2 等待線(xiàn)程 T1 占有的資源,就是循環(huán)等待。

如何解決死鎖呢?打破任意一個(gè)條件即可。

其中,互斥這個(gè)條件我們沒(méi)有辦法破壞,因?yàn)槲覀冇面i為的就是互斥。不過(guò)其他三個(gè)條件都是有辦法破壞掉的,到底如何做呢?

對(duì)于“占用且等待”這個(gè)條件,我們可以一次性申請(qǐng)所有的資源,這樣就不存在等待了。對(duì)于“不可搶占”這個(gè)條件,占用部分資源的線(xiàn)程進(jìn)一步申請(qǐng)其他資源時(shí),如果申請(qǐng)不到,可以主動(dòng)釋放它占有的資源,這樣不可搶占這個(gè)條件就破壞掉了。對(duì)于“循環(huán)等待”這個(gè)條件,可以靠按序申請(qǐng)資源來(lái)預(yù)防。所謂按序申請(qǐng),是指資源是有線(xiàn)性順序的,申請(qǐng)的時(shí)候可以先申請(qǐng)資源序號(hào)小的,再申請(qǐng)資源序號(hào)大的,這樣線(xiàn)性化后自然就不存在循環(huán)了。

好了,回到正題上來(lái),既然我們的思路就是拿不到資源就選擇退讓?zhuān)覀兛梢越栌肑ava里的ReentrantLock類(lèi)中trylock()方法實(shí)現(xiàn),該方法的作用就是嘗試鎖住該資源。和lock()方法不同的是,如果該資源已經(jīng)上鎖,那么線(xiàn)程不會(huì)阻塞,而是返回flase,表示無(wú)法上鎖,當(dāng)然還可以加入?yún)?shù)讓它再?lài)L試幾秒,比如:

lock.tryLock(1, TimeUnit.SECONDS));

而具體用法就是

if (lock.tryLock(1, TimeUnit.SECONDS)) {
    try {
        ...
    } finally {
        lock.unlock();
    }
}

三、代碼實(shí)現(xiàn)

package com.dreamchaser.concurrent;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 哲學(xué)家就餐問(wèn)題
 */
public class Proj3_02 {
    static final Lock[] locks=new Lock[5];
    static {
        for (int i=0;i<locks.length;i++){
            locks[i]=new ReentrantLock();
        }
    }

    public static void main(String[] args) {
        Philosopher philosopher0=new Philosopher("張三",1000,0);
        Philosopher philosopher1=new Philosopher("李四",800,1);
        Philosopher philosopher2=new Philosopher("王五",400,2);
        Philosopher philosopher3=new Philosopher("jhl",2000,3);
        Philosopher philosopher4=new Philosopher("ghlcl",2000,4);
        philosopher0.start();
        philosopher1.start();
        philosopher2.start();
        philosopher3.start();
        philosopher4.start();
        //死循環(huán),防止主線(xiàn)程退出導(dǎo)致進(jìn)程關(guān)閉
        while (true){}
    }

    static class Philosopher extends Thread{
        private String name;
        private long time;
        private int num;

        public Philosopher(String name, long time, int num) {
            this.name = name;
            this.time = time;
            this.num = num;
        }

        @Override
        public void run() {
            while (true){
                System.out.println(num+"號(hào)哲學(xué)家"+name+"正在思考...");
                //模擬思考的過(guò)程
                try {
                    Thread.sleep(time);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(num+"號(hào)哲學(xué)家"+name+"餓了,想來(lái)吃飯...");
                if (locks[num].tryLock()){
                    try {
                        System.out.println(num+"號(hào)哲學(xué)家"+name+"拿到了左邊的筷子!");
                        if (locks[(num+1)%5].tryLock()){
                            try {
                                System.out.println(num+"號(hào)哲學(xué)家"+name+"拿到了右邊的筷子!");
                                System.out.println(num+"號(hào)哲學(xué)家"+name+"開(kāi)始吃飯!");
                                //模擬哲學(xué)家吃飯的過(guò)程
                                Thread.sleep(time);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            } finally {
                                System.out.println(num+"號(hào)哲學(xué)家"+name+"放下了右邊的筷子!");
                                locks[(num+1)%5].unlock();
                            }
                        }else {
                            System.out.println(num+"號(hào)哲學(xué)家"+name+"沒(méi)拿到了右邊的筷子!被迫思考...");
                        }
                    }finally {
                        System.out.println(num+"號(hào)哲學(xué)家"+name+"放下了左邊的筷子!");
                        locks[num].unlock();
                    }
                }else {
                    System.out.println(num+"號(hào)哲學(xué)家"+name+"沒(méi)拿到了左邊的筷子!被迫思考...");
                }
                System.out.println(num+"號(hào)哲學(xué)家"+name+"思考ing...");
                //模擬思考過(guò)程
                try {
                    Thread.sleep(time);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

四、運(yùn)行效果截圖

在這里插入圖片描述

在這里插入圖片描述

五、結(jié)語(yǔ)

以上是我的實(shí)現(xiàn)思路。希望我的思路能個(gè)各位有所幫助,當(dāng)然,如果有什么意見(jiàn)或者建議的,歡迎在評(píng)論區(qū)評(píng)論。

到此這篇關(guān)于Java多線(xiàn)程之哲學(xué)家就餐問(wèn)題詳解的文章就介紹到這了,更多相關(guān)Java哲學(xué)家就餐詳解內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • SpringBoot整合FTP使用示例教程

    SpringBoot整合FTP使用示例教程

    這篇文章主要介紹了SpringBoot整合FTP使用示例教程,本文通過(guò)示例代碼給大家介紹的非常詳細(xì),感興趣的朋友跟隨小編一起看看吧
    2024-08-08
  • Spring?WebMVC初始化Controller流程詳解

    Spring?WebMVC初始化Controller流程詳解

    這篇文章主要介紹了Spring?WebMVC初始化Controller流程,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-02-02
  • IDEA創(chuàng)建Maven項(xiàng)目一直顯示正在加載的問(wèn)題及解決

    IDEA創(chuàng)建Maven項(xiàng)目一直顯示正在加載的問(wèn)題及解決

    這篇文章主要介紹了IDEA創(chuàng)建Maven項(xiàng)目一直顯示正在加載的問(wèn)題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-12-12
  • 基于Java實(shí)現(xiàn)計(jì)數(shù)排序,桶排序和基數(shù)排序

    基于Java實(shí)現(xiàn)計(jì)數(shù)排序,桶排序和基數(shù)排序

    這篇文章主要為大家詳細(xì)介紹了計(jì)數(shù)排序,桶排序和基數(shù)排序的多種語(yǔ)言的實(shí)現(xiàn)(JavaScript、Python、Go語(yǔ)言、Java),感興趣的小伙伴可以了解一下
    2022-12-12
  • springboot 整合druid數(shù)據(jù)庫(kù)密碼加密功能的實(shí)現(xiàn)代碼

    springboot 整合druid數(shù)據(jù)庫(kù)密碼加密功能的實(shí)現(xiàn)代碼

    這篇文章主要介紹了springboot 整合druid數(shù)據(jù)庫(kù)密碼加密功能的實(shí)現(xiàn)代碼,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-01-01
  • 詳解java操作Redis數(shù)據(jù)庫(kù)的redis工具(RedisUtil,jedis工具JedisUtil,JedisPoolUtil)

    詳解java操作Redis數(shù)據(jù)庫(kù)的redis工具(RedisUtil,jedis工具JedisUtil,JedisPoo

    這篇文章主要介紹了java操作Redis數(shù)據(jù)庫(kù)的redis工具,包括RedisUtil,jedis工具JedisUtil,JedisPoolUtil工具,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2021-08-08
  • Java多線(xiàn)程并發(fā)FutureTask使用詳解

    Java多線(xiàn)程并發(fā)FutureTask使用詳解

    Java?的多線(xiàn)程機(jī)制本質(zhì)上能夠完成兩件事情,異步計(jì)算和并發(fā),F(xiàn)utureTask?是基于?Runnable?實(shí)現(xiàn)的一個(gè)可取消的異步調(diào)用?API,本文給大家介紹Java?多線(xiàn)程并發(fā)FutureTask及基本使用,需要的朋友可以參考下
    2022-06-06
  • JPA如何使用findBy方法自定義查詢(xún)

    JPA如何使用findBy方法自定義查詢(xún)

    這篇文章主要介紹了JPA如何使用findBy方法自定義查詢(xún),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-11-11
  • Idea創(chuàng)建多模塊maven聚合項(xiàng)目的實(shí)現(xiàn)

    Idea創(chuàng)建多模塊maven聚合項(xiàng)目的實(shí)現(xiàn)

    這篇文章主要介紹了Idea創(chuàng)建多模塊maven聚合項(xiàng)目的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-12-12
  • Spring系列之事物管理

    Spring系列之事物管理

    這篇文章主要介紹了Spring系列之事物管理,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用spring方面知識(shí)具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們一起學(xué)習(xí)學(xué)習(xí)吧
    2021-09-09

最新評(píng)論