2016-04-20 59 views
1

试图通过创建一个门卫来解决哲学家的餐饮问题,只允许4位哲学家一次性用餐,计划使用信号量但是关于它们的材料有限网络,我不知道如何增加信号量的值,一旦它已被发信号。如何增加C++中的信号量值来解决哲学家用餐

#define INITIAL_COUNT 1 
#define MAX_COUNT 4 

主()

philo.doorSemaphore = CreateSemaphore(
    NULL,   //default security attributes 
    INITIAL_COUNT, //initial count 
    MAX_COUNT, //maximum count 

    NULL); 

while (philo.not_dead == true) 
{ 
    int num_philosophers = 5; 
    for (int i = 0; i < 5; i++) 
    { 
     philo.mythread[i] = thread (philosophersFunction, i);  //init 5 threads calling philofunction each loop 
     philo.mythread[i].join();         //join thread to current thread each loop 
    } 
    sleep_for(milliseconds(500)); 
    system("cls"); 
} 

等待()

void Philosophers::waiting(int current) 
{ 

dWaitResult = WaitForSingleObject(doorSemaphore, 0L); 
//waitResult = WaitForSingleObject(semaphores, 0L); 

switch (dWaitResult) 
{ 
case WAIT_OBJECT_0: 
    p[current] = hungry; 
    ReleaseSemaphore(doorSemaphore, 1, NULL); 
    break; 
case WAIT_TIMEOUT: 
    hunger[current] ++; 
    counter[current] ++; 
case WAIT_FAILED : 
    break; 

    CloseHandle(doorSemaphore); 
    } 
} 
+1

您正在将Windows WinAPI线程库函数与C++标准线程库混合使用。从标准中选择一些:http://en.cppreference.com/w/cpp/thread – marcinj

回答

1

Dining Philosophers Rebooted是利用现代C++与std::threadstd::mutex此经典问题的彻底治疗。完整的源代码可在链接中找到。

此代码的工作原理是将每个叉子代表为std::mutex。然后诀窍是如何同时锁定两个互斥锁而不会造成死锁。 C++十四分之十一带有一个功能明确地用于此目的:

template <class L1, class L2, class... L3> 
    void lock(L1&, L2&, L3&...); 

上述文章探讨的std::lock几个可能的实施方式为2互斥和3互斥的情况下,和识别一个算法,该算法从未任何低于第任何其他算法(通常好得多)。

最佳实现(根据本文)实际上是libc++使用的算法。

下面是在纸的“2-d”情况下,Philosopher::eat()功能:

void 
Philosopher::eat() 
{ 
    using Lock = std::unique_lock<std::mutex>; 
    Lock first; 
    Lock second; 
    if (flip_coin()) 
    { 
     first = Lock(left_fork_, std::defer_lock); 
     second = Lock(right_fork_, std::defer_lock); 
    } 
    else 
    { 
     first = Lock(right_fork_, std::defer_lock); 
     second = Lock(left_fork_, std::defer_lock); 
    } 
    auto d = get_eat_duration(); 
    ::lock(first, second); 
    auto end = std::chrono::steady_clock::now() + d; 
    while (std::chrono::steady_clock::now() < end) 
     ; 
    eat_time_ += d; 
} 

出于演示的目的而已,Philosopher随机地选择在左手和右手持有该叉。这个随机性并不是解决问题所必需的。该功能可以被简化为以下,仍然是正确的:

void 
Philosopher::eat() 
{ 
    using Lock = std::unique_lock<std::mutex>; 
    Lock first { left_fork_, std::defer_lock}; 
    Lock second{right_fork_, std::defer_lock}; 
    auto d = get_eat_duration(); 
    ::lock(first, second); 
    auto end = std::chrono::steady_clock::now() + d; 
    while (std::chrono::steady_clock::now() < end) 
     ; 
    eat_time_ += d; 
} 

在实际的代码中调用::lock应该std::lock,但是这个代码正在尝试的std::lock几种实现无创性改变的std :: LIB 。