具有条件变量的两个互斥锁以锁定一个类,线程

时间:2019-05-11 21:54:08

标签: c++ multithreading mutex thread-synchronization

我正在尝试使用chandy-misra算法解决食堂哲学家的问题。此处提供更多说明:https://en.wikipedia.org/wiki/Dining_philosophers_problem

我正在使用一个互斥锁来锁定修改后的变量,而另一个使用条件变量来锁定何时可以免费使用fork。

我看不出我的所有哲学家都在同一时间进餐的原因-他们根本不在等待其他叉子。似乎我使用的互斥锁错误。

哲学家线程:

void philosopher::dine() {
    while(!is_initialized); // here threads waits until all other philosophers are initialized                                                
    while(!is_stopped) {
        eat();
        think(); // here just sleeps for a few seconds
    }
}

饮食方法:

void philosopher::eat() {
    left_fork.request(index);
    right_fork.request(index);

    std::lock(right_fork.get_mutex(), left_fork.get_mutex());                
    std::lock_guard<std::mutex> l1( right_fork.get_mutex(), std::adopt_lock );    
    std::lock_guard<std::mutex> l2( left_fork.get_mutex(), std::adopt_lock );

    int num = distribution(mt);
    std::cout << "Philsopher " << index << " eats for " << num 
               << "seconds." << std::endl;
    sleep(num);
    right_fork.free();
    left_fork.free();
}

fork类的外观:

enum fork_state {
    CLEAN, DIRTY
};

class fork_t {
    int index;
    int owner_id;
    mutable std::mutex condition_m;
    std::mutex owner_m;
    std::condition_variable condition;

    public:
    fork_t(int _index,int _owner_id);
    fork_t(const fork_t &f);
    void request(int phil_req);
    void free();
    std::mutex &get_mutex() { return owner_m; }
    fork_t& operator=(fork_t const &f);
};

void fork_t::request(int phil_req) {

    while (owner_id != phil_req ) {

        std::unique_lock<std::mutex> l(condition_m);

        if(state == DIRTY) {
            std::lock_guard<std::mutex> lock(owner_m);            
            state = CLEAN;
            owner_id = phil_req;
        } else {
            while(state == CLEAN) {
               std::cout<<"Philosopher " << phil_req << " is waiting for"<< index <<std::endl;
                condition.wait(l);
            }
        }
    }
}

void fork_t::free() {
    state = DIRTY;
    condition.notify_one();
}

一开始,所有的分叉都交给了ID较低的哲学家。 我将不胜感激。

0 个答案:

没有答案