`
tinggo
  • 浏览: 44890 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

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 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倍,毕竟别人不是核心对象。
分享到:
评论

相关推荐

    Win32多线程程序设计.pdf(带目录)

    Win32 API提供了多种同步对象,如互斥量(Mutex)、信号量(Semaphore)、事件(Event)和临界区(CriticalSection)。每种同步对象都有其适用场景和特点,例如,互斥量适合保护全局变量,而临界区则提供了轻量级的...

    《Win32多线程程序设计》配套代码

    《Win32多线程程序设计》是一本深入探讨Windows操作系统环境下如何开发多线程应用程序的专业书籍。书中详细讲解了如何利用Win32 API来创建、管理以及同步多个执行线程,以实现高效的并发处理。配套代码包含了书中...

    Win32多线程程序设计及配套源码

    线程间通信是多线程编程的关键,Win32 API提供了多种同步机制,如事件对象(Event)、互斥量(Mutex)、信号量(Semaphore)和临界区(Critical Section)。这些机制用于控制对共享资源的访问,防止竞态条件和死锁的...

    Win32 多线程程序设计 光盘源代码 侯捷

    此外,线程间的数据共享和保护也是多线程编程的关键,`Mutex`、`Semaphore`、`CriticalSection`等同步对象可以帮助开发者解决这些问题,防止数据竞争和死锁的发生。 本书的光盘源代码包含了许多示例程序,这些示例...

    Win32多线程程序设计 (源代码)

    标题"Win32多线程程序设计 (源代码)"暗示了我们将深入探讨如何在Win32环境下创建和管理多线程程序,并通过实际的源代码来学习这一过程。 Win32 API提供了丰富的函数和结构来支持多线程编程。创建一个线程首先需要...

    Win32多线程程序设计(pdf加全书签)

    《Win32多线程程序设计》是一本深入探讨C++在Win32平台上实现多线程编程的专业书籍。该书全面覆盖了多线程技术的基础理论与实践应用,为开发者提供了详尽的指导。书中的"加全书签"功能使得读者能够更方便地定位和...

    pthread和win32的临界区 Critical Section 比较

    临界区(Critical Section)是线程同步的一种基本方法,它在不同的操作系统和编程库中有不同的实现。本文将深入探讨pthread和Win32 API中的临界区实现,并进行比较。 首先,让我们了解临界区的基本概念。临界区是指...

    Win32多线程程序设计源码

    在Windows编程领域,Win32 API是开发人员创建应用程序的基础工具集,它提供了丰富的功能,包括多线程编程...通过研究这些源码,你可以加深对Win32多线程编程的理解,学习如何在实践中解决线程同步、通信和管理等问题。

    Win32多线程程序设计

    本文将深入探讨由候杰老师翻译的《Win32多线程程序设计》一书中涉及的关键概念和技术。 多线程是现代计算机程序设计中一个重要的概念,它允许多个执行流同时进行,提高了处理器的利用率和程序的响应速度。在Win32 ...

    Win32多线程程序设计源码.rar

    在Windows编程环境中,Win32 API是开发人员用于创建应用...通过研究"Win32多线程程序设计源码",开发者可以深入了解Win32 API在多线程环境下的应用,学习如何有效地编写和管理多线程程序,提升软件的效率和用户体验。

    Win32多线程程序设计.pdf

    《Win32多线程程序设计》是一本深入探讨Windows操作系统环境下多线程编程的权威指南。这本书详尽地介绍了如何在Win32 API中创建、管理以及优化多线程应用,是开发者学习多线程技术的重要参考资料。下面将详细阐述多...

    Win32多线程程序设计(随书源码)

    Win32 API提供了多种同步机制,如临界区(Critical Section)、互斥量(Mutex)、信号量(Semaphore)以及事件(Event),用于控制对共享资源的访问,避免数据竞争和死锁的发生。临界区适用于同步同一进程内的线程,而互斥量...

    Win32 多线程程序设计完全手册PDF,本书详细讲解了多线程程序设计。

    《Win32多线程程序设计完全手册》是一本深入探讨Windows操作系统环境下多线程编程技术的专业书籍。在计算机科学中,多线程是并行处理的一种方式,它允许一个应用程序同时执行多个任务,从而提高了系统的效率和响应...

    win32多线程程序设计源码_侯捷

    这个资源可能包括了一系列的示例代码、讲解文档,旨在帮助开发者深入理解和实践win32 API中的多线程编程技术。 在Windows操作系统中,多线程编程是并发执行任务的一种方式,可以提高系统资源的利用率和程序的响应...

    Win32 多线程程序设计(pdf)

    Win32 API提供了多种同步机制,如临界区(Critical Section)、互斥量(Mutex)、事件对象(Event)、信号量(Semaphore)等,用于防止数据竞争和确保线程安全。临界区和互斥量主要用于保护共享资源,而事件对象和...

    Win32多线程程序设计(源代码).rar

    通过学习和实践这些源代码,开发者可以掌握Win32多线程编程的核心技术,提升自己的并发编程能力,为开发高性能、高并发的Windows应用程序打下坚实基础。此外,理解多线程的正确使用方式也能帮助开发者避免潜在的性能...

    Win32 多线程程序设计(候捷译).rar

    《Win32 多线程程序设计》是程序员们深入理解Windows系统下多线程编程的重要参考资料。...通过学习,开发者能够熟练掌握如何在Win32环境中创建、管理、通信和优化多线程程序,从而提升软件的并发处理能力和效率。

    Win32 多线程程序设计_纯文本转成的PDF

    3. **线程同步**:这是多线程编程中的核心问题,包括临界区(Critical Section)、信号量(Semaphore)、事件(Event)、互斥量(Mutex)等同步机制的使用,以及如何避免死锁和竞态条件。 4. **线程通信**:线程间通信的...

    win32多线程程序设计 书中示例代码

    在《win32多线程程序设计》一书中,侯捷先生将详细讲解这些概念,并通过实际的代码示例(如`multiThreading_demo`中的代码)帮助读者理解和掌握Win32平台下的多线程编程。这本书对于想要提升Windows系统下多线程编程...

Global site tag (gtag.js) - Google Analytics