Windows下的多线程

时间:2021-08-03 17:38:09

本文转载自https://www.jum1023.com/index.php/2018/01/23/multithread/

Windows下多线程的同步与互斥

critical section

#include <stdio.h>
#include <process.h>
#include <windows.h>

// Usage
// EnterCriticalSection(CRITICAL_SECTION)
// ...//do some thing
// LeaveCriticalSection(CRITICAL_SECTION)

long global;
unsigned int __stdcall ThreadFunction(void *handle);
const int THREAD_NUM = 10; //if the number is more than 100,there will be a question
// definition of critical section
CRITICAL_SECTION g_csThreadCode
;

int main()
{
// initialize critical section
InitializeCriticalSection(&g_csThreadCode);

HANDLE handle
[THREAD_NUM];
global = 0;
int i = 0;
while (i < THREAD_NUM)
{
handle
[i] = (HANDLE)_beginthreadex(NULL, 0, ThreadFunction, &i, 0, NULL);
++i;
}
WaitForMultipleObjects(THREAD_NUM, handle, TRUE, INFINITE); //wait for all threads to finish the task
DeleteCriticalSection(&g_csThreadCode);

return 0;
}

unsigned int __stdcall ThreadFunction(void *handle)
{
EnterCriticalSection(&g_csThreadCode); // enter critical section
global++;
Sleep(0); //重新发起一次CPU竞争
printf
("global variable is %d\n",global);
LeaveCriticalSection(&g_csThreadCode);
return 0;
}

这个例子当线程数设置为150时,我的主机就无法正常全部打印了

mutex

// 互斥量Mutex:
// Usage
// WaitForSingleObject(hMutex,…);
// ...//do something
// ReleaseMutex(hMutex);

#include <stdio.h>
#include <process.h>
#include <windows.h>

long global;
unsigned int __stdcall ThreadFunction(void *handle);
const int THREAD_NUM = 10;
// 互斥量
HANDLE hmutex
;

int main()
{
// 初始化互斥量,第二个参数为TRUE表示互斥量为创建进程所有
hmutex
= CreateMutex(NULL, FALSE, NULL);

HANDLE handle
[THREAD_NUM];
global = 0;
int i = 0;
while (i < THREAD_NUM)
{
handle
[i] = (HANDLE)_beginthreadex(NULL, 0, ThreadFunction, &i, 0, NULL);
i
++;
}
WaitForMultipleObjects(THREAD_NUM, handle, TRUE, INFINITE);
// 销毁互斥量
CloseHandle(hmutex);
return 0;
}

unsigned int __stdcall ThreadFunction(void *handle)
{
WaitForSingleObject(hmutex, INFINITE); // 等待互斥量被触发
global++;
Sleep(0);
printf
("global variable is %d\n", global);
ReleaseMutex(hmutex); // 触发互斥量
return 0;
}

互斥量和关键段的区别互斥量可以设置等待时间

event

// Usage
// SetEvent(hEvent);
// WaitForSingleObject(hEvent,…);
// 等待其他进程的setevent,然后执行操作

#include <stdio.h>
#include <process.h>
#include <windows.h>
long global;
unsigned int __stdcall ThreadFunction(void *handle);
const int THREAD_NUM = 10;
//事件
HANDLE hevent
;
int main()
{
//初始化事件初
hevent
= CreateEvent(NULL, FALSE, FALSE, NULL);
HANDLE handle
[THREAD_NUM];
global = 0;
int i = 0;
SetEvent(hevent); //如果这一行注释,则事件没有触发,所有线程等待
while (i < THREAD_NUM)
{
handle
[i] = (HANDLE)_beginthreadex(NULL, 0, ThreadFunction, &i, 0, NULL);
i
++;
}
WaitForMultipleObjects(THREAD_NUM, handle, TRUE, INFINITE);
//销毁事件
CloseHandle(hevent);
return 0;
}
unsigned int __stdcall ThreadFunction(void *handle)
{
WaitForSingleObject(hevent,INFINITE);
global++;
Sleep(0);
printf
("global variable is %d\n",global);
SetEvent(hevent); //触发事件
return 0;
}

事件更适合一个线程像另一个线程发送通知消息

semaphore

// WaitForSingleObject(hsemaphore,INFINITE);
// ...//do something
// ReleaseSemaphore(hsemaphore, 1, NULL);

#include <stdio.h>
#include <process.h>
#include <windows.h>

long global;
unsigned int __stdcall ThreadFunction(void *handle);
const int THREAD_NUM = 10;
// 信号量
HANDLE hsemaphore
;

int main()
{
// 初始化信号量和关键段
hsemaphore
= CreateSemaphore(NULL, 0, 1, NULL); // 当前0个资源,最大允许1个同时访问
ReleaseSemaphore(hsemaphore, 1, NULL); // 信号量++,多出一个资源,如果注释掉,所有线程等待
HANDLE handle
[THREAD_NUM];
global = 0;
int i = 0;
while (i < THREAD_NUM)
{
handle
[i] = (HANDLE)_beginthreadex(NULL, 0, ThreadFunction, &i, 0, NULL);
++i;
}
WaitForMultipleObjects(THREAD_NUM, handle, TRUE, INFINITE);

// 销毁信号量
CloseHandle(hsemaphore);
return 0;
}

unsigned int __stdcall ThreadFunction(void *handle)
{
WaitForSingleObject(hsemaphore,INFINITE);
global++;
Sleep(0);
printf
("global variable is %d\n",global);
ReleaseSemaphore(hsemaphore, 1, NULL); // 信号量++
return 0;
}

semaphore针对资源而言,对于一个区间允许有多个线程访问

以上几种方法的对比

critical section mutex event semaphore
非内核 内核 内核 内核
只能同步单个进程的线程     属于PV操作
可以由软件层面忙等来实现 互斥量是可以命名的,也就是说它可以跨越进程使用 主要用于消息通知等 允许多个线程在同一时刻访问同一资源,但是需要限制在同一时刻访问此资源的最大线程数目

进程互斥的软件解决方法

  • Use two shared data items
int turn; //指示该谁进入临界区 
bool flag[]; //指示进程是否准备好进入临界区
  • code for enter critical section
flag[i] = TRUE;
turn
= j;
while(flag[j]&&turn==j);
  • code for exit critical section
flag[j]=FALSE;

其他基于硬件的原子操作

Windows下的多线程