- 浏览: 44730 次
- 性别:
- 来自: 上海
最新评论
-
HappyBlueCat:
关于你的JAVA问题,提下我的看法:关于这方面,JAVA和C、 ...
对于JAVA中passed by reference & passed by value -
ZangXT:
java的引用其实就是指针,不过在语言层面对它可以进行的操作进 ...
对于JAVA中passed by reference & passed by value
最近学习多线程编程,并且以Win32作为实验平台,看了点东西感觉应该稍微有所实践。
因此拿了哲学家进餐问题作了实验品,以来检验最近学习CriticalSection和Mutex的成果
哲学家进餐问题我做了稍微的简化,没有什么左边一个筷子和又边一个筷子。全部简化为总共6根筷子和六个傻冒哲学家,然后大家一起米西米西。
任务目标
1.模拟死锁的发生
2.用CriticalSection解除死锁
3.用Mutex解除死锁
1. 模拟死锁的发生
结果发现6位傻冒很快就进入相互等待死锁的状态。
然后使用CriticalSection来解除死锁
结果发现再也没有死锁过,然后使用Mutex来解除死锁
下一篇将会使用Event来完成上述相同的任务。
今天顺便参考了一下其他已成的代码,发现对于互斥的情况下,使用CriticalSection比较多,当然他的缺点就是不能够在进程间形成互斥,但是他的速度是Mutex的100倍,毕竟别人不是核心对象。
因此拿了哲学家进餐问题作了实验品,以来检验最近学习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多线程学习之二(实现生产者与消费者模型)
2011-10-13 21:51 1314#include <Windows.h> # ... -
深入理解C++中多态的实现
2010-12-22 22:29 1519对于C++中多态性是面向 ... -
[转]追MM与Java的23种设计模式
2010-09-19 21:21 952追MM与Java的23种设计模 ... -
关于C++引用类型变量
2010-09-05 12:01 2388随着设计模式的学习和 ... -
【转】拷贝构造函数和赋值函数的必要性和意义
2010-03-10 23:01 2818引用链接: http://hi.baidu ... -
深入理解计算机系统验证代码1
2010-01-23 21:35 1431/* 此程序测试了深入理解计算机系统中的 1. ... -
《代码揭秘》阅读有感一
2009-10-17 22:36 15792009-10-17 《代码揭秘》阅读有感一 今天,《代码揭 ... -
C++编译、链接过程
2009-07-30 23:10 6166C++程序从编译到链接然后再到调用的整个过程如下。 只是个人最 ... -
链接器都干了些什么
2009-07-27 00:13 1229目前项目在不停的增长 ... -
程序中的堆和栈
2009-04-26 01:20 1003[转载]栈和堆的区别 信 ...
相关推荐
Win32 API提供了多种同步对象,如互斥量(Mutex)、信号量(Semaphore)、事件(Event)和临界区(CriticalSection)。每种同步对象都有其适用场景和特点,例如,互斥量适合保护全局变量,而临界区则提供了轻量级的...
《Win32多线程程序设计》是一本深入探讨Windows操作系统环境下如何开发多线程应用程序的专业书籍。书中详细讲解了如何利用Win32 API来创建、管理以及同步多个执行线程,以实现高效的并发处理。配套代码包含了书中...
线程间通信是多线程编程的关键,Win32 API提供了多种同步机制,如事件对象(Event)、互斥量(Mutex)、信号量(Semaphore)和临界区(Critical Section)。这些机制用于控制对共享资源的访问,防止竞态条件和死锁的...
此外,线程间的数据共享和保护也是多线程编程的关键,`Mutex`、`Semaphore`、`CriticalSection`等同步对象可以帮助开发者解决这些问题,防止数据竞争和死锁的发生。 本书的光盘源代码包含了许多示例程序,这些示例...
标题"Win32多线程程序设计 (源代码)"暗示了我们将深入探讨如何在Win32环境下创建和管理多线程程序,并通过实际的源代码来学习这一过程。 Win32 API提供了丰富的函数和结构来支持多线程编程。创建一个线程首先需要...
《Win32多线程程序设计》是一本深入探讨C++在Win32平台上实现多线程编程的专业书籍。该书全面覆盖了多线程技术的基础理论与实践应用,为开发者提供了详尽的指导。书中的"加全书签"功能使得读者能够更方便地定位和...
临界区(Critical Section)是线程同步的一种基本方法,它在不同的操作系统和编程库中有不同的实现。本文将深入探讨pthread和Win32 API中的临界区实现,并进行比较。 首先,让我们了解临界区的基本概念。临界区是指...
在Windows编程领域,Win32 API是开发人员创建应用程序的基础工具集,它提供了丰富的功能,包括多线程编程...通过研究这些源码,你可以加深对Win32多线程编程的理解,学习如何在实践中解决线程同步、通信和管理等问题。
本文将深入探讨由候杰老师翻译的《Win32多线程程序设计》一书中涉及的关键概念和技术。 多线程是现代计算机程序设计中一个重要的概念,它允许多个执行流同时进行,提高了处理器的利用率和程序的响应速度。在Win32 ...
在Windows编程环境中,Win32 API是开发人员用于创建应用...通过研究"Win32多线程程序设计源码",开发者可以深入了解Win32 API在多线程环境下的应用,学习如何有效地编写和管理多线程程序,提升软件的效率和用户体验。
《Win32多线程程序设计》是一本深入探讨Windows操作系统环境下多线程编程的权威指南。这本书详尽地介绍了如何在Win32 API中创建、管理以及优化多线程应用,是开发者学习多线程技术的重要参考资料。下面将详细阐述多...
Win32 API提供了多种同步机制,如临界区(Critical Section)、互斥量(Mutex)、信号量(Semaphore)以及事件(Event),用于控制对共享资源的访问,避免数据竞争和死锁的发生。临界区适用于同步同一进程内的线程,而互斥量...
《Win32多线程程序设计完全手册》是一本深入探讨Windows操作系统环境下多线程编程技术的专业书籍。在计算机科学中,多线程是并行处理的一种方式,它允许一个应用程序同时执行多个任务,从而提高了系统的效率和响应...
这个资源可能包括了一系列的示例代码、讲解文档,旨在帮助开发者深入理解和实践win32 API中的多线程编程技术。 在Windows操作系统中,多线程编程是并发执行任务的一种方式,可以提高系统资源的利用率和程序的响应...
Win32 API提供了多种同步机制,如临界区(Critical Section)、互斥量(Mutex)、事件对象(Event)、信号量(Semaphore)等,用于防止数据竞争和确保线程安全。临界区和互斥量主要用于保护共享资源,而事件对象和...
通过学习和实践这些源代码,开发者可以掌握Win32多线程编程的核心技术,提升自己的并发编程能力,为开发高性能、高并发的Windows应用程序打下坚实基础。此外,理解多线程的正确使用方式也能帮助开发者避免潜在的性能...
《Win32 多线程程序设计》是程序员们深入理解Windows系统下多线程编程的重要参考资料。...通过学习,开发者能够熟练掌握如何在Win32环境中创建、管理、通信和优化多线程程序,从而提升软件的并发处理能力和效率。
3. **线程同步**:这是多线程编程中的核心问题,包括临界区(Critical Section)、信号量(Semaphore)、事件(Event)、互斥量(Mutex)等同步机制的使用,以及如何避免死锁和竞态条件。 4. **线程通信**:线程间通信的...