news 2026/4/29 9:02:10

C++ 如何实现多线程与线程同步

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
C++ 如何实现多线程与线程同步

CreateThread 实现多线程:

先来创建一个简单的多线程实例,无参数传递版,运行实例会发现,主线程与子线程运行无规律。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

#include <windows.h>

#include <iostream>

usingnamespacestd;

DWORDWINAPI Func(LPVOIDlpParamter)

{

for(intx = 0; x < 10; x++)

{

cout <<"thread function"<< endl;

Sleep(200);

}

return0;

}

intmain(intargc,char* argv[])

{

HANDLEhThread = CreateThread(NULL, 0, Func, NULL, 0, NULL);

CloseHandle(hThread);

for(intx = 0; x < 10; x++)

{

cout <<"main thread"<< endl;

Sleep(400);

}

system("pause");

return0;

}

beginthreadex 实现多线程:

这个方法与前面的CreateThread使用完全一致,只是在参数上面应使用void *该参数可以强转为任意类型,两者实现效果完全一致。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

#include <windows.h>

#include <iostream>

#include <process.h>

usingnamespacestd;

unsigned WINAPI Func(void*arg)

{

for(intx = 0; x < 10; x++)

{

cout <<"thread function"<< endl;

Sleep(200);

}

return0;

}

intmain(intargc,char* argv[])

{

HANDLEhThread = (HANDLE)_beginthreadex(NULL, 0, Func, NULL, 0, NULL);

CloseHandle(hThread);

for(intx = 0; x < 10; x++)

{

cout <<"main thread"<< endl;

Sleep(400);

}

system("pause");

return0;

}

CreateMutex 互斥锁实现线程同步:

使用互斥锁可以实现单位时间内,只允许一个线程拥有对共享资源的独占,从而实现了互不冲突的线程同步。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

#include <windows.h>

#include <iostream>

usingnamespacestd;

HANDLEhMutex = NULL;// 创建互斥锁

// 线程函数

DWORDWINAPI Func(LPVOIDlpParamter)

{

for(intx = 0; x < 10; x++)

{

// 请求获得一个互斥锁

WaitForSingleObject(hMutex, INFINITE);

cout <<"thread func"<< endl;

// 释放互斥锁

ReleaseMutex(hMutex);

}

return0;

}

intmain(intargc,char* argv[])

{

HANDLEhThread = CreateThread(NULL, 0, Func, NULL, 0, NULL);

hMutex = CreateMutex(NULL, FALSE,"lyshark");

CloseHandle(hThread);

for(intx = 0; x < 10; x++)

{

// 请求获得一个互斥锁

WaitForSingleObject(hMutex, INFINITE);

cout <<"main thread"<< endl;

// 释放互斥锁

ReleaseMutex(hMutex);

}

system("pause");

return0;

}

通过互斥锁,同步执行两个线程函数。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

#include <windows.h>

#include <iostream>

usingnamespacestd;

HANDLEhMutex = NULL;// 创建互斥锁

#define NUM_THREAD 50

// 线程函数1

DWORDWINAPI FuncA(LPVOIDlpParamter)

{

for(intx = 0; x < 10; x++)

{

// 请求获得一个互斥锁

WaitForSingleObject(hMutex, INFINITE);

cout <<"this is thread func A"<< endl;

// 释放互斥锁

ReleaseMutex(hMutex);

}

return0;

}

// 线程函数2

DWORDWINAPI FuncB(LPVOIDlpParamter)

{

for(intx = 0; x < 10; x++)

{

// 请求获得一个互斥锁

WaitForSingleObject(hMutex, INFINITE);

cout <<"this is thread func B"<< endl;

// 释放互斥锁

ReleaseMutex(hMutex);

}

return0;

}

intmain(intargc,char* argv[])

{

// 用来存储线程函数的句柄

HANDLEtHandle[NUM_THREAD];

// /创建互斥量,此时为signaled状态

hMutex = CreateMutex(NULL, FALSE,"lyshark");

for(intx = 0; x < NUM_THREAD; x++)

{

if(x % 2)

{

tHandle[x] = CreateThread(NULL, 0, FuncA, NULL, 0, NULL);

}

else

{

tHandle[x] = CreateThread(NULL, 0, FuncB, NULL, 0, NULL);

}

}

// 等待所有线程函数执行完毕

WaitForMultipleObjects(NUM_THREAD, tHandle, TRUE, INFINITE);

// 销毁互斥对象

CloseHandle(hMutex);

system("pause");

return0;

}

通过临界区实现线程同步:

临界区与互斥锁差不多,临界区使用时会创建CRITICAL_SECTION临界区对象,同样相当于一把钥匙,线程函数执行结束自动上交,如下是临界区函数的定义原型。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

//初始化函数原型

VOIDInitializeCriticalSection(

LPCRITICAL_SECTION lpCriticalSection

);

//销毁函数原型

VOIDDeleteCriticalSection(

LPCRITICAL_SECTION lpCriticalSection

);

//获取

VOIDEnterCriticalSection(

LPCRITICAL_SECTION lpCriticalSection

);

//释放

VOIDLeaveCriticalSection(

LPCRITICAL_SECTION lpCriticalSection

);

这一次我们不适用互斥体,使用临界区实现线程同步,结果与互斥体完全一致,看个人喜好。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

#include <windows.h>

#include <iostream>

usingnamespacestd;

CRITICAL_SECTION cs;// 全局定义临界区对象

#define NUM_THREAD 50

// 线程函数

DWORDWINAPI FuncA(LPVOIDlpParamter)

{

for(intx = 0; x < 10; x++)

{

//进入临界区

EnterCriticalSection(&cs);

cout <<"this is thread func A"<< endl;

//离开临界区

LeaveCriticalSection(&cs);

}

return0;

}

intmain(intargc,char* argv[])

{

// 用来存储线程函数的句柄

HANDLEtHandle[NUM_THREAD];

//初始化临界区

InitializeCriticalSection(&cs);

for(intx = 0; x < NUM_THREAD; x++)

{

tHandle[x] = CreateThread(NULL, 0, FuncA, NULL, 0, NULL);

}

// 等待所有线程函数执行完毕

WaitForMultipleObjects(NUM_THREAD, tHandle, TRUE, INFINITE);

//释放临界区

DeleteCriticalSection(&cs);

system("pause");

return0;

}

Semaphore 基于信号实现线程同步:

通过定义一个信号,初始化信号为0,利用信号量值为0时进入non-signaled状态,大于0时进入signaled状态的特性即可实现线程同步。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

#include <windows.h>

#include <iostream>

usingnamespacestd;

staticHANDLESemaphoreOne;

staticHANDLESemaphoreTwo;

// 线程函数1

DWORDWINAPI FuncA(LPVOIDlpParamter)

{

for(intx = 0; x < 10; x++)

{

// 临界区开始时设置 signaled 状态

WaitForSingleObject(SemaphoreOne, INFINITE);

cout <<"this is thread func A"<< endl;

// 临界区结束则设置为 non-signaled 状态

ReleaseSemaphore(SemaphoreOne, 1, NULL);

}

return0;

}

// 线程函数2

DWORDWINAPI FuncB(LPVOIDlpParamter)

{

for(intx = 0; x < 10; x++)

{

// 临界区开始时设置 signaled 状态

WaitForSingleObject(SemaphoreTwo, INFINITE);

cout <<"this is thread func B"<< endl;

// 临界区结束则设置为 non-signaled 状态

ReleaseSemaphore(SemaphoreTwo, 1, NULL);

}

return0;

}

intmain(intargc,char* argv[])

{

// 用来存储线程函数的句柄

HANDLEhThreadA, hThreadB;

// 创建信号量对象,并且设置为0进入non-signaled状态

SemaphoreOne = CreateSemaphore(NULL, 0, 1, NULL);

// 创建信号量对象,并且设置为1进入signaled状态

SemaphoreTwo = CreateSemaphore(NULL, 1, 1, NULL);// 先执行这一个线程函数

hThreadA = CreateThread(NULL, 0, FuncA, NULL,0, NULL);

hThreadB = CreateThread(NULL, 0, FuncB, NULL, 0, NULL);

// 等待两个线程函数执行完毕

WaitForSingleObject(hThreadA, INFINITE);

WaitForSingleObject(hThreadA, INFINITE);

// 销毁两个线程函数

CloseHandle(SemaphoreOne);

CloseHandle(SemaphoreTwo);

system("pause");

return0;

}

上面的一段代码,容易产生死锁现象,即,线程函数B执行完成后,A函数一直处于等待状态。

执行WaitForSingleObject(semTwo, INFINITE);会让线程函数进入类似挂起的状态,当接到ReleaseSemaphore(semOne, 1, NULL);才会恢复执行。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

#include <windows.h>

#include <stdio.h>

staticHANDLEsemOne,semTwo;

staticintnum;

// 线程函数A用于接收参书

DWORDWINAPI ReadNumber(LPVOIDlpParamter)

{

inti;

for(i = 0; i < 5; i++)

{

fputs("Input Number: ", stdout);

//临界区的开始 signaled状态

WaitForSingleObject(semTwo, INFINITE);

scanf("%d", &num);

//临界区的结束 non-signaled状态

ReleaseSemaphore(semOne, 1, NULL);

}

return0;

}

// 线程函数B: 用户接受参数后完成计算

DWORDWINAPI Check(LPVOIDlpParamter)

{

intsum = 0, i;

for(i = 0; i < 5; i++)

{

//临界区的开始 non-signaled状态

WaitForSingleObject(semOne, INFINITE);

sum += num;

//临界区的结束 signaled状态

ReleaseSemaphore(semTwo, 1, NULL);

}

printf("The Number IS: %d \n", sum);

return0;

}

intmain(intargc,char*argv[])

{

HANDLEhThread1, hThread2;

//创建信号量对象,设置为0进入non-signaled状态

semOne = CreateSemaphore(NULL, 0, 1, NULL);

//创建信号量对象,设置为1进入signaled状态

semTwo = CreateSemaphore(NULL, 1, 1, NULL);

hThread1 = CreateThread(NULL, 0, ReadNumber, NULL, 0, NULL);

hThread2 = CreateThread(NULL, 0, Check, NULL, 0, NULL);

// 关闭临界区

WaitForSingleObject(hThread1, INFINITE);

WaitForSingleObject(hThread2, INFINITE);

CloseHandle(semOne);

CloseHandle(semTwo);

system("pause");

return0;

}

CreateEvent 事件对象的同步:

事件对象实现线程同步,与前面的临界区和互斥体有很大的不同,该方法下创建对象时,可以在自动non-signaled状态运行的auto-reset模式,当我们设置好我们需要的参数时,可以直接使用SetEvent(hEvent)设置事件状态,会自动执行线程函数。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/29 8:59:04

Hotkey Detective 深度解析:Windows 热键监控架构与实现原理

Hotkey Detective 深度解析&#xff1a;Windows 热键监控架构与实现原理 【免费下载链接】hotkey-detective A small program for investigating stolen key combinations under Windows 7 and later. 项目地址: https://gitcode.com/gh_mirrors/ho/hotkey-detective Wi…

作者头像 李华