哲学家吃饭 and 顺序吃法

不按顺序吃法,将死锁的“循环等待”条件破坏即可,我的做法是奇数先拿左手筷子,偶数先拿右手筷子。

代码如下

#include <iostream>
#include <thread>
#include <mutex>
#include <vector>
#include <set>
#include <future>

const int num_philosophers = 5;
std::atomic<int> cnt(0); 

// 筷子类,用于控制哲学家的行为
class Chopstick {
private:
    std::mutex mutex; // 互斥锁,用于保证只有一个哲学家能够拿起这根筷子
public:
    // 拿起筷子
    void pickUp() {
        mutex.lock();
    }
    // 放下筷子
    void putDown() {
        mutex.unlock();
    }
};

// 哲学家类
class Philosopher {
private:
    int id; // 哲学家的编号
    Chopstick& firstChopstick; // 第一双获取的筷子
    Chopstick& secondChopstick; // 第二双获取的筷子

public:
    // 构造函数
    Philosopher(int id, Chopstick& first_chopstick, Chopstick& second_chopstick)
        : id(id), firstChopstick(first_chopstick), secondChopstick(second_chopstick) {}
    // 进餐的函数
    void dine() {
        while(1)
        {
            std::this_thread::sleep_for(std::chrono::milliseconds(1));
            // 开始进餐
            firstChopstick.pickUp();
            secondChopstick.pickUp();
            cnt.fetch_add(1);
            std::cout << "哲学家 " << id << " 完成用餐.  当前计数:" << cnt.load() << std::endl;
            // 完成进餐
            firstChopstick.putDown();
            secondChopstick.putDown();
        }
    }
};

int main() {
    std::vector<Chopstick> chopsticks(num_philosophers); // 创建筷子
    std::vector<Philosopher> philosophers; // 创建哲学家
    // 创建哲学家对象并放入容器中
    for (int i = 0; i < num_philosophers; ++i) {
        if (i % 2)
            philosophers.emplace_back(i, chopsticks[i], chopsticks[(i + 1) % num_philosophers]);
        else
            philosophers.emplace_back(i, chopsticks[(i + 1) % num_philosophers], chopsticks[i]);
    }

    // 启动线程
    std::vector<std::thread> threads;
    for (int i = num_philosophers - 1; i >= 0; --i) {
        threads.emplace_back(&Philosopher::dine, &philosophers[i]);
    }

    // 等待所有线程结束
    for (auto& thread : threads) {
        thread.join();
    }
    return 0;
}

需要按顺序吃饭时。这里使用waitnotify_*实现

wait notify就是锁,被notify唤醒了才会去拿筷子,一次只会有一个线程在跑,根本就不需要大锁,换成5把小锁即可。筷子也不需要锁。

#include <iostream>
#include <thread>
#include <mutex>
#include <vector>
#include <set>
#include <future>

std::mutex cnt_mtx;
const int num_philosophers = 5;
std::vector<std::condition_variable> cv(num_philosophers);
std::vector<std::mutex> mtx(num_philosophers);
std::vector<int>ready(num_philosophers, 0);
std::atomic<int> cnt(0); 

// 筷子类,用于控制哲学家的行为
class Chopstick {
public:
    // 拿起筷子
    void pickUp() {
    }
    // 放下筷子
    void putDown() {
    }
};

// 哲学家类
class Philosopher {
private:
    int id; // 哲学家的编号
    Chopstick& firstChopstick; // 第一双获取的筷子
    Chopstick& secondChopstick; // 第二双获取的筷子
public:
    // 构造函数
    Philosopher(int id, Chopstick& first_chopstick, Chopstick& second_chopstick)
        : id(id), firstChopstick(first_chopstick), secondChopstick(second_chopstick) {}
    // 进餐的函数
    void dine() {
        while(1)
        {    
            std::unique_lock<std::mutex> lck(mtx[id]);
            while(ready[id] != 1) cv[id].wait(lck);
            ready[id] = 0;
            std::this_thread::sleep_for(std::chrono::milliseconds(1));
            // 开始进餐
            firstChopstick.pickUp();
            secondChopstick.pickUp();
            cnt.fetch_add(1);
            std::cout << "哲学家 " << id << " 完成用餐.  当前计数:" << cnt.load() << std::endl;
            ready[(id+1) % num_philosophers] = 1;
            cv[(id+1) % num_philosophers].notify_one();
            // 完成进餐
            firstChopstick.putDown();
            secondChopstick.putDown();
        }
    }
};

void go() {
    std::this_thread::sleep_for(std::chrono::milliseconds(1000)); //要sleep,保证在所有线程创建完成之后才运行
    std::unique_lock<std::mutex> lck(mtx[num_philosophers-1]);
    ready[0] = 1;
    cv[0].notify_one();
}
int main() {
    std::vector<Chopstick> chopsticks(num_philosophers); // 创建筷子
    std::vector<Philosopher> philosophers; // 创建哲学家
    // 创建哲学家对象并放入容器中
    for (int i = 0; i < num_philosophers; ++i) {
        if (i % 2)
            philosophers.emplace_back(i, chopsticks[i], chopsticks[(i + 1) % num_philosophers]);
        else
            philosophers.emplace_back(i, chopsticks[(i + 1) % num_philosophers], chopsticks[i]);
    }
    // 启动线程
    std::vector<std::thread> threads;
    for (int i = num_philosophers - 1; i >= 0; --i) {
        threads.emplace_back(&Philosopher::dine, &philosophers[i]);
    }
    std::cout << "main: " << cnt.load() << std::endl;
    go();
    // 等待所有线程结束
    for (auto& thread : threads) {
        thread.join();
    }
    return 0;
}
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇