读书人

Win32多线程学习之一(CriticalSectio

发布时间: 2012-12-24 10:43:13 作者: rapoo

Win32多线程学习之一(CriticalSection和Mutex)
最近学习多线程编程,并且以Win32作为实验平台,看了点东西感觉应该稍微有所实践。
因此拿了哲学家进餐问题作了实验品,以来检验最近学习CriticalSection和Mutex的成果

哲学家进餐问题我做了稍微的简化,没有什么左边一个筷子和又边一个筷子。全部简化为总共6根筷子和六个傻冒哲学家,然后大家一起米西米西。

任务目标
1.模拟死锁的发生
2.用CriticalSection解除死锁
3.用Mutex解除死锁

1. 模拟死锁的发生

// Philosopher problem#include <windows.h>#include <stdio.h>#include <time.h>const int MAX_TIME = 5;bool chopsticks[6] = {false, false, false, false, false, false};class Philosopher{private:char* name;HANDLE philosopherOperation;DWORD threadId;int firstChopstickIndex;int secondChopstickIndex;public:Philosopher(const char* name): firstChopstickIndex(-1), secondChopstickIndex(-1){SetName(name);philosopherOperation = CreateThread(NULL, 0, Philosopher::BeginOperation, this, 0, &threadId);}void SetName(const char* name){this->name = const_cast<char*>(name);}static DWORD WINAPI BeginOperation(LPVOID p){Philosopher* pointer = reinterpret_cast<Philosopher*>(p);while(true){pointer->Thinking();pointer->Waiting();pointer->Eating();}return 0;}void Thinking(){int time = rand() % 5 + 1;printf("%s think for %d seconds\n", this->name, time);Sleep(time * 1000);}void Eating(){int time = rand()% 5 + 1;printf("%s eat for %d seconds\n", this->name, time);Sleep(time * 1000);chopsticks[firstChopstickIndex] = false;chopsticks[secondChopstickIndex] = false;firstChopstickIndex = -1;secondChopstickIndex = -1;}void Waiting(){while(true){if (firstChopstickIndex == -1){for (int i = 0; i < 6; ++i){if (!chopsticks[i]){chopsticks[i] = true;firstChopstickIndex = i;break;}      }}Sleep(0.5*1000); //Make it easy to reproduce thread dead lockif (secondChopstickIndex == -1){for (int i = 0; i < 6; ++i){if (!chopsticks[i]){chopsticks[i] = true;secondChopstickIndex = i;break;}}}if (firstChopstickIndex != -1 && secondChopstickIndex != -1){return;}else{printf("%s is waiting\n", this->name);}}}};void Initialize(){srand((unsigned int)time(NULL)); // set random seed}void BeginEmulate(){Philosopher p1("XYT");Philosopher p2("WS");Philosopher p3("WL");Philosopher p4("WYF");Philosopher p5("LLB");Philosopher p6("JXL");Sleep(3600 * 1000);}int main(){Initialize();BeginEmulate();return 0;}


结果发现6位傻冒很快就进入相互等待死锁的状态。
然后使用CriticalSection来解除死锁
// Philosopher problem#include <windows.h>#include <stdio.h>#include <time.h>const int MAX_TIME = 5;bool chopsticks[6] = {false, false, false, false, false, false};CRITICAL_SECTION criticalSection;class Philosopher{private:    char* name;    HANDLE philosopherOperation;    DWORD threadId;    int firstChopstickIndex;    int secondChopstickIndex;public:    Philosopher(const char* name): firstChopstickIndex(-1), secondChopstickIndex(-1)    {        SetName(name);        philosopherOperation = CreateThread(NULL, 0, Philosopher::BeginOperation, this, 0, &threadId);    }    void SetName(const char* name)    {        this->name = const_cast<char*>(name);    }    static DWORD WINAPI BeginOperation(LPVOID p)    {        Philosopher* pointer = reinterpret_cast<Philosopher*>(p);        while(true)        {            pointer->Thinking();            pointer->Waiting();            pointer->Eating();        }        return 0;    }    void Thinking()    {        int time = rand() % 5 + 1;        printf("%s think for %d seconds\n", this->name, time);        Sleep(time * 1000);    }    void Eating()    {        int time = rand()% 5 + 1;        printf("%s eat for %d seconds\n", this->name, time);        Sleep(time * 1000);        chopsticks[firstChopstickIndex] = false;        chopsticks[secondChopstickIndex] = false;        firstChopstickIndex = -1;        secondChopstickIndex = -1;    }    void Waiting()    {        while(true)        {            // add critical             EnterCriticalSection(&criticalSection);            if (firstChopstickIndex == -1)            {                for (int i = 0; i < 6; ++i)                {                   if (!chopsticks[i])                    {                        chopsticks[i] = true;                        firstChopstickIndex = i;                        break;                    }                      }            }            Sleep(0.5*1000); //Make it easy to reproduce thread dead lock            if (secondChopstickIndex == -1)            {                for (int i = 0; i < 6; ++i)                {                    if (!chopsticks[i])                    {                        chopsticks[i] = true;                        secondChopstickIndex = i;                        break;                    }                }            }            LeaveCriticalSection(&criticalSection);            if (firstChopstickIndex != -1 && secondChopstickIndex != -1)            {                return;            }            else            {                printf("%s is waiting\n", this->name);                //Sleep(1000);            }        }    }};void Initialize(){    InitializeCriticalSection(&criticalSection);    srand((unsigned int)time(NULL)); // set random seed}void BeginEmulate(){    Philosopher p1("XYT");    Philosopher p2("WS");    Philosopher p3("WL");    Philosopher p4("WYF");    Philosopher p5("LLB");    Philosopher p6("JXL");    Sleep(3600 * 1000);}int main(){    Initialize();    BeginEmulate();    DeleteCriticalSection(&criticalSection);    return 0;}

结果发现再也没有死锁过,然后使用Mutex来解除死锁
// Philosopher problem#include <windows.h>#include <stdio.h>#include <time.h>const int MAX_TIME = 5;bool chopsticks[6] = {false, false, false, false, false, false};HANDLE mutex;class Philosopher{private:char* name;HANDLE philosopherOperation;DWORD threadId;int firstChopstickIndex;int secondChopstickIndex;public:Philosopher(const char* name): firstChopstickIndex(-1), secondChopstickIndex(-1){SetName(name);philosopherOperation = CreateThread(NULL, 0, Philosopher::BeginOperation, this, 0, &threadId);}void SetName(const char* name){this->name = const_cast<char*>(name);}static DWORD WINAPI BeginOperation(LPVOID p){Philosopher* pointer = reinterpret_cast<Philosopher*>(p);while(true){pointer->Thinking();pointer->Waiting();pointer->Eating();}return 0;}void Thinking(){int time = rand() % 5 + 1;printf("%s think for %d seconds\n", this->name, time);Sleep(time * 1000);}void Eating(){int time = rand()% 5 + 1;printf("%s eat for %d seconds\n", this->name, time);Sleep(time * 1000);chopsticks[firstChopstickIndex] = false;chopsticks[secondChopstickIndex] = false;firstChopstickIndex = -1;secondChopstickIndex = -1;}void Waiting(){while(true){// add critical WaitForSingleObject(mutex, INFINITE);if (firstChopstickIndex == -1){for (int i = 0; i < 6; ++i){if (!chopsticks[i]){chopsticks[i] = true;firstChopstickIndex = i;break;}      }}Sleep(0.5*1000); //Make it easy to reproduce thread dead lockif (secondChopstickIndex == -1){for (int i = 0; i < 6; ++i){if (!chopsticks[i]){chopsticks[i] = true;secondChopstickIndex = i;break;}}}ReleaseMutex(mutex);if (firstChopstickIndex != -1 && secondChopstickIndex != -1){return;}else{printf("%s is waiting\n", this->name);//Sleep(1000);}}}};void Initialize(){mutex = CreateMutex(NULL, false, NULL);srand((unsigned int)time(NULL)); // set random seed}void BeginEmulate(){Philosopher p1("XYT");Philosopher p2("WS");Philosopher p3("WL");Philosopher p4("WYF");Philosopher p5("LLB");Philosopher p6("JXL");Sleep(3600 * 1000);}int main(){Initialize();BeginEmulate();CloseHandle(mutex);return 0;}


下一篇将会使用Event来完成上述相同的任务。
今天顺便参考了一下其他已成的代码,发现对于互斥的情况下,使用CriticalSection比较多,当然他的缺点就是不能够在进程间形成互斥,但是他的速度是Mutex的100倍,毕竟别人不是核心对象。

读书人网 >编程

热点推荐