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;}
// 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;}
// 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;}