并发concurent与并行parallel的区别:
- 互斥对象
首先我们需要创建CreateMutex一把互斥对象,我们可以指明当前线程是否拥有它,互斥对象完全就像一把钥匙一样,我们用WaitForSignalObject来等待这把钥匙,但是这把钥匙被等到并且使用后必须释放-----ReleaseMutex ,不然别人永远无法等到。这样从等待到释放中间的代码段永远都是只有一个线程在执行,也就形成了互斥控制。当然互斥对象的句柄是要关闭的CloseHandle。
#include<windows.h>
#include<iostream>
using namespace std;
int ticket = 100;
HANDLE hMutex; //定义互斥对象
DWORD WINAPI FuncProc1(LPVOID lpParameter);
DWORD WINAPI FuncProc2(LPVOID lpParameter);
int main()
{
hMutex = CreateMutex(NULL, FALSE, NULL); //定义互斥对象,并让该线程不拥有它
HANDLE hThread1 = CreateThread(NULL, 0, FuncProc1, NULL, 0, NULL);
HANDLE hThread2 = CreateThread(NULL,0, FuncProc2, NULL, 0, NULL);
CloseHandle(hThread1);
CloseHandle(hThread2);
Sleep(1000); //让主线程睡眠1秒
return 0;
}
DWORD WINAPI FuncProc1(LPVOID lpParameter) {
while (true) {
WaitForSingleObject(hMutex, INFINITE);
if (ticket > 0) {
Sleep(1);
cout << "ticket1 :" << ticket-- << endl;
}
else
break;
ReleaseMutex(hMutex);
}
return 0;
}
DWORD WINAPI FuncProc2(LPVOID lpParameter) {
while (true) {
WaitForSingleObject(hMutex, INFINITE); //申请互斥对象的所有权
if (ticket > 0) {
Sleep(1);
cout << "ticket2 :" << ticket-- << endl;
}
else
break;
ReleaseMutex(hMutex); //释放互斥对象的所有权
}
return 0;
}
注意:
虽然改程序运行结果是某一条线程执行完然后第二条线程执行,如此往复,但是这不是同步,因为我们没法控制到底一开始是谁先执行,(我们只是控制了轮流次序)。
- 事件
首先我们需要创建CreateEvent一个事件对象,它的使用方式是触发方式,要想被WaitForSingleObject等待到该事件对象必须是有信号的,事件要想有信号可以用SetEvent手动置为有信号,要想事件对象无信号可以使用ResetEvent(或者在创建事件对象时就声明),该事件对象在WaitForSingleObject后自动置为无信号,见上面CreateEvent第二个参数),打个小小比方,手动置位事件相当于教室门,教室门一旦打开(被触发),所以有人都可以进入直到老师去关上教室门(事件变成未触发)。自动置位事件就相当于医院里拍X光的房间门,门打开后只能进入一个人,这个人进去后会将门关上,其它人不能进入除非门重新被打开(事件重新被触发)。当然事件对象的句柄是要关闭的CloseHandle。
#include<windows.h>
#include<iostream>
using namespace std;
int ticket = 100;
HANDLE g_hEvent;
DWORD WINAPI FuncProc1(LPVOID lpParameter);
DWORD WINAPI FuncProc2(LPVOID lpParameter);
int main()
{
//参数意义:默认安全性,自动重置事件,初始时该事件对象就有信号
g_hEvent = CreateEvent(NULL, FALSE, TRUE, NULL);
HANDLE hThread1 = CreateThread(NULL, 0, FuncProc1, NULL, 0, NULL);
HANDLE hThread2 = CreateThread(NULL,0, FuncProc2, NULL, 0, NULL);
CloseHandle(hThread1);
CloseHandle(hThread2);
Sleep(1000); //让主线程睡眠1秒
CloseHandle(g_hEvent);
return 0;
}
DWORD WINAPI FuncProc1(LPVOID lpParameter) {
while (true) {
WaitForSingleObject(g_hEvent, INFINITE); //申请事件对象(申请钥匙,持有钥匙)
if (ticket > 0) {
Sleep(1);
cout << "ticket1 :" << ticket-- << endl;
SetEvent(g_hEvent); //(放弃钥匙,不在拥有)
}
else
{
SetEvent(g_hEvent); //设置为有信号
break;
}
}
return 0;
}
DWORD WINAPI FuncProc2(LPVOID lpParameter) {
while (true) {
WaitForSingleObject(g_hEvent, INFINITE); //申请事件对象(申请钥匙,持有钥匙)
if (ticket > 0) {
Sleep(1);
cout << "ticket2 :" << ticket-- << endl;
SetEvent(g_hEvent); //(放弃钥匙,不在拥有)
}
else
{
SetEvent(g_hEvent); //设置为有信号
break;
}
}
return 0;
}
改进:具有严格的同步控制
#include<windows.h>
#include<iostream>
using namespace std;
int ticket = 100;
HANDLE g_hEvent1;
HANDLE g_hEvent2;
DWORD WINAPI FuncProc1(LPVOID lpParameter);
DWORD WINAPI FuncProc2(LPVOID lpParameter);
int main()
{
g_hEvent1 = CreateEvent(NULL, FALSE, TRUE, NULL); //创建事件对象
g_hEvent2 = CreateEvent(NULL, FALSE, FALSE, NULL); //创建事件对象
HANDLE hThread1 = CreateThread(NULL, 0, FuncProc1, NULL, 0, NULL);
HANDLE hThread2 = CreateThread(NULL,0, FuncProc2, NULL, 0, NULL);
CloseHandle(hThread1);
CloseHandle(hThread2);
Sleep(1000); //让主线程睡眠1秒
CloseHandle(g_hEvent1);
CloseHandle(g_hEvent2);
return 0;
}
DWORD WINAPI FuncProc1(LPVOID lpParameter) {
while (true) {
WaitForSingleObject(g_hEvent1, INFINITE); //申请事件对象(申请钥匙,持有钥匙)
if (ticket > 0) {
Sleep(1);
cout << "ticket1 :" << ticket-- << endl;
SetEvent(g_hEvent2); //让线程2执行
}
else
{
SetEvent(g_hEvent2); //让线程2执行
break;
}
}
return 0;
}
DWORD WINAPI FuncProc2(LPVOID lpParameter) {
while (true) {
WaitForSingleObject(g_hEvent2, INFINITE); //申请事件对象(申请钥匙,持有钥匙)
if (ticket > 0) {
Sleep(1);
cout << "ticket2 :" << ticket-- << endl;
SetEvent(g_hEvent1); //让线程1执行
}
else
{
SetEvent(g_hEvent1); //让线程1执行
break;
}
}
return 0;
}
- 临界区
#include<iostream>
#include "windows.h"
using namespace std;
DWORD WINAPI FunProc1(LPVOID lpParameter);
DWORD WINAPI FunProc2(LPVOID lpParameter);
int ticket = 1000;
CRITICAL_SECTION g_cs;
int main()
{
InitializeCriticalSection(&g_cs); //初始化临界区
HANDLE hThread1 = CreateThread(NULL, 0, FunProc1, NULL, 0, NULL);
HANDLE hThread2 = CreateThread(NULL, 0, FunProc2, NULL, 0, NULL);
CloseHandle(hThread1);
CloseHandle(hThread2);
Sleep(1000);
DeleteCriticalSection(&g_cs); //删除临界区
return 0;
}
DWORD WINAPI FunProc1(LPVOID lpParameter)
{
while (TRUE) {
EnterCriticalSection(&g_cs); //进入临界区
Sleep(1);
if (ticket > 0) {
Sleep(1);
cout << "ticket1: " << ticket-- << endl;
LeaveCriticalSection(&g_cs); //离开临界区
}
else {
LeaveCriticalSection(&g_cs); //离开
break;
}
}
return 0;
}
DWORD WINAPI FunProc2(LPVOID lpParameter)
{
while (TRUE) {
EnterCriticalSection(&g_cs);
Sleep(1);
if (ticket > 0) {
Sleep(1);
cout << "ticket2: " << ticket-- << endl;
LeaveCriticalSection(&g_cs);
}
else {
LeaveCriticalSection(&g_cs);
break;
}
}
return 0;
}
https://blog.youkuaiyun.com/ebowtang/article/details/29905309