Win32多线程学习之一(CriticalSection和Mutex)_C/C++_编程开发_程序员俱乐部

中国优秀的程序员网站程序员频道CXYCLUB技术地图
热搜:
更多>>
 
您所在的位置: 程序员俱乐部 > 编程开发 > C/C++ > Win32多线程学习之一(CriticalSection和Mutex)

Win32多线程学习之一(CriticalSection和Mutex)

 2011/9/21 8:10:52  tinggo  http://tinggo.iteye.com  我要评论(0)
  • 摘要:最近学习多线程编程,并且以Win32作为实验平台,看了点东西感觉应该稍微有所实践。因此拿了哲学家进餐问题作了实验品,以来检验最近学习CriticalSection和Mutex的成果哲学家进餐问题我做了稍微的简化,没有什么左边一个筷子和又边一个筷子。全部简化为总共6根筷子和六个傻冒哲学家,然后大家一起米西米西。任务目标1.模拟死锁的发生2.用CriticalSection解除死锁3.用Mutex解除死锁1.模拟死锁的发生//Philosopherproblem#include<
  • 标签:学习 多线程
最近学习多线程编程,并且以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 lock
			if (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 lock
			if (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倍,毕竟别人不是核心对象。
发表评论
用户名: 匿名