#include
#include
#include
// 定义全局变量
CRITICAL_SECTION g_cs;
unsigned int __stdcall ThreadFun1(PVOID lpParam)
{
//申请进入临界区
EnterCriticalSection(&g_cs);
int number = (int)lpParam;
//获取当前线程id
DWORD threadId = GetCurrentThreadId();
while (number > 0) {
printf("thread id is %d, number is %d\n", threadId, number--);
Sleep(1000);
}
//离开临界区
LeaveCriticalSection(&g_cs);
return 0;
}
unsigned int __stdcall ThreadFun2(PVOID lpParam)
{
//申请进入临界区
EnterCriticalSection(&g_cs);
int number = (int)lpParam;
//获取当前线程id
DWORD threadId = GetCurrentThreadId();
while (number > 0) {
printf("thread id is %d, number is %d\n", threadId, number--);
Sleep(1000);
}
//离开临界区
LeaveCriticalSection(&g_cs);
return 0;
}
unsigned int __stdcall ThreadFun3(PVOID lpParam)
{
//申请进入临界区
EnterCriticalSection(&g_cs);
int number = (int)lpParam;
//获取当前线程id
DWORD threadId = GetCurrentThreadId();
while (number > 0) {
printf("thread id is %d, number is %d\n", threadId, number--);
Sleep(1000);
}
//离开临界区
LeaveCriticalSection(&g_cs);
return 0;
}
int main()
{
unsigned ThreadID1 = 0;
unsigned ThreadID2 = 0;
unsigned ThreadID3 = 0;
// 初始化临界区对象
InitializeCriticalSection(&g_cs);
//创建线程
HANDLE handle1 = (HANDLE)_beginthreadex(NULL, 0, ThreadFun1, (void*)5, 0, &ThreadID1);
HANDLE handle2 = (HANDLE)_beginthreadex(NULL, 0, ThreadFun2, (void*)5, 0, &ThreadID2);
HANDLE handle3 = (HANDLE)_beginthreadex(NULL, 0, ThreadFun3, (void*)5, 0, &ThreadID3);
printf("main function thread1 id is %d\n", ThreadID1);
printf("main function thread2 id is %d\n", ThreadID2);
printf("main function thread3 id is %d\n", ThreadID3);
//永久等待线程运行结束
WaitForSingleObject(handle1, INFINITE);
WaitForSingleObject(handle2, INFINITE);
WaitForSingleObject(handle3, INFINITE);
//删除临界区对象
DeleteCriticalSection(&g_cs);
//关闭线程句柄
CloseHandle(handle1);
CloseHandle(handle2);
CloseHandle(handle3);
system("pause");
return 0;
}
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
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
运行结果
从运行结果可以看到,这三个线程之间实现了互斥,即一个线程执行完另一个线程才会执行
main function thread1 id is 21072
main function thread2 id is 41576
main function thread3 id is 16796
thread id is 21072, number is 5
thread id is 21072, number is 4
thread id is 21072, number is 3
thread id is 21072, number is 2
thread id is 21072, number is 1
thread id is 41576, number is 5
thread id is 41576, number is 4
thread id is 41576, number is 3
thread id is 41576, number is 2
thread id is 41576, number is 1
thread id is 16796, number is 5
thread id is 16796, number is 4
thread id is 16796, number is 3
thread id is 16796, number is 2
thread id is 16796, number is 1
请按任意键继续. . .
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
如果我们删除对线程的互斥控制,再看下执行结果,可以很清楚的看出区别
main function thread1 id is 13796
main function thread2 id is 41216
main function thread3 id is 7088
thread id is 41216, number is 5
thread id is 13796, number is 5
thread id is 7088, number is 5
thread id is 7088, number is 4
thread id is 13796, number is 4
thread id is 41216, number is 4
thread id is 7088, number is 3
thread id is 13796, number is 3
thread id is 41216, number is 3
thread id is 13796, number is 2
thread id is 41216, number is 2
thread id is 7088, number is 2
thread id is 13796, number is 1
thread id is 7088, number is 1
thread id is 41216, number is 1
请按任意键继续. . .
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2.2、事件内核对象
实现步骤
全局
定义一个全局变量
主线程中
创建自动重置,未受信的事件内核对象
创建线程
触发事件
等待线程运行结束
关闭内核对象
关闭线程句柄
子线程中
等待事件触发
进行相关工作
重新触发事件
编码实现
#include
#include
#include
// 定义全局变量
HANDLE g_hEvent;
unsigned int __stdcall ThreadFun1(PVOID lpParam)
{
//等待事件触发
WaitForSingleObject(g_hEvent, INFINITE);
int number = (int)lpParam;
//获取当前线程id
DWORD threadId = GetCurrentThreadId();
while (number > 0) {
printf("thread id is %d, number is %d\n", threadId, number--);
Sleep(1000);
}
//重新触发事件
SetEvent(g_hEvent);
return 0;
}
unsigned int __stdcall ThreadFun2(PVOID lpParam)
{
//等待事件触发
WaitForSingleObject(g_hEvent, INFINITE);
int number = (int)lpParam;
//获取当前线程id
DWORD threadId = GetCurrentThreadId();
while (number > 0) {
printf("thread id is %d, number is %d\n", threadId, number--);
Sleep(1000);
}
//重新触发事件
SetEvent(g_hEvent);
return 0;
}
unsigned int __stdcall ThreadFun3(PVOID lpParam)
{
//等待事件触发
WaitForSingleObject(g_hEvent, INFINITE);
int number = (int)lpParam;
//获取当前线程id
DWORD threadId = GetCurrentThreadId();
while (number > 0) {
printf("thread id is %d, number is %d\n", threadId, number--);
Sleep(1000);
}
//重新触发事件
SetEvent(g_hEvent);
return 0;
}
int main()
{
unsigned ThreadID1 = 0;
unsigned ThreadID2 = 0;
unsigned ThreadID3 = 0;
// 创建自动重置,未受信的事件内核对象
g_hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
//创建线程
HANDLE handle1 = (HANDLE)_beginthreadex(NULL, 0, ThreadFun1, (void*)5, 0, &ThreadID1);
HANDLE handle2 = (HANDLE)_beginthreadex(NULL, 0, ThreadFun2, (void*)5, 0, &ThreadID2);
HANDLE handle3 = (HANDLE)_beginthreadex(NULL, 0, ThreadFun3, (void*)5, 0, &ThreadID3);
printf("main function thread1 id is %d\n", ThreadID1);
printf("main function thread2 id is %d\n", ThreadID2);
printf("main function thread3 id is %d\n", ThreadID3);
//触发事件
SetEvent(g_hEvent);
//永久等待线程运行结束
WaitForSingleObject(handle1, INFINITE);
WaitForSingleObject(handle2, INFINITE);
WaitForSingleObject(handle3, INFINITE);
//关闭内核对象
CloseHandle(g_hEvent);
//关闭线程句柄
CloseHandle(handle1);
CloseHandle(handle2);
CloseHandle(handle3);
system("pause");
return 0;
}
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
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
运行结果
main function thread1 id is 43624
main function thread2 id is 42564
main function thread3 id is 43648
thread id is 43624, number is 5
thread id is 43624, number is 4
thread id is 43624, number is 3
thread id is 43624, number is 2
thread id is 43624, number is 1
thread id is 42564, number is 5
thread id is 42564, number is 4
thread id is 42564, number is 3
thread id is 42564, number is 2
thread id is 42564, number is 1
thread id is 43648, number is 5
thread id is 43648, number is 4
thread id is 43648, number is 3
thread id is 43648, number is 2
thread id is 43648, number is 1
请按任意键继续. . .
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2.3、互斥量
实现步骤
全局
定义一个互斥量
主线程
创建互斥量
创建线程
等待线程运行结束
关闭线程句柄
删除互斥量
子线程
等待互斥量
释放互斥量
编码实现
#include
#include
#include
// 定义互斥量
HANDLE hMutex;
unsigned int __stdcall ThreadFun1(PVOID lpParam)
{
//等待互斥量
WaitForSingleObject(hMutex, INFINITE);
int number = (int)lpParam;
//获取当前线程id
DWORD threadId = GetCurrentThreadId();
while (number > 0) {
printf("thread id is %d, number is %d\n", threadId, number--);
Sleep(1000);
}
//释放互斥量
ReleaseMutex(hMutex);
return 0;
}
unsigned int __stdcall ThreadFun2(PVOID lpParam)
{
//等待互斥量
WaitForSingleObject(hMutex, INFINITE);
int number = (int)lpParam;
//获取当前线程id
DWORD threadId = GetCurrentThreadId();
while (number > 0) {
printf("thread id is %d, number is %d\n", threadId, number--);
Sleep(1000);
}
//释放互斥量
ReleaseMutex(hMutex);
return 0;
}
unsigned int __stdcall ThreadFun3(PVOID lpParam)
{
//等待互斥量
WaitForSingleObject(hMutex, INFINITE);
int number = (int)lpParam;
//获取当前线程id
DWORD threadId = GetCurrentThreadId();
while (number > 0) {
printf("thread id is %d, number is %d\n", threadId, number--);
Sleep(1000);
}
//释放互斥量
ReleaseMutex(hMutex);
return 0;
}
int main()
{
unsigned ThreadID1 = 0;
unsigned ThreadID2 = 0;
unsigned ThreadID3 = 0;
// 创建互斥量
hMutex = CreateMutex(NULL, FALSE, NULL);
//创建线程
HANDLE handle1 = (HANDLE)_beginthreadex(NULL, 0, ThreadFun1, (void*)5, 0, &ThreadID1);
HANDLE handle2 = (HANDLE)_beginthreadex(NULL, 0, ThreadFun2, (void*)5, 0, &ThreadID2);
HANDLE handle3 = (HANDLE)_beginthreadex(NULL, 0, ThreadFun3, (void*)5, 0, &ThreadID3);
printf("main function thread1 id is %d\n", ThreadID1);
printf("main function thread2 id is %d\n", ThreadID2);
printf("main function thread3 id is %d\n", ThreadID3);
//永久等待线程运行结束
WaitForSingleObject(handle1, INFINITE);
WaitForSingleObject(handle2, INFINITE);
WaitForSingleObject(handle3, INFINITE);
//关闭线程句柄
CloseHandle(handle1);
CloseHandle(handle2);
CloseHandle(handle3);
//删除互斥量
CloseHandle(hMutex);
system("pause");
return 0;
}
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
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
运行结果
main function thread1 id is 42112
main function thread2 id is 43136
main function thread3 id is 9128
thread id is 42112, number is 5
thread id is 42112, number is 4
thread id is 42112, number is 3
thread id is 42112, number is 2
thread id is 42112, number is 1
thread id is 43136, number is 5
thread id is 43136, number is 4
thread id is 43136, number is 3
thread id is 43136, number is 2
thread id is 43136, number is 1
thread id is 9128, number is 5
thread id is 9128, number is 4
thread id is 9128, number is 3
thread id is 9128, number is 2
thread id is 9128, number is 1
请按任意键继续. . .
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2.4、信号量
实现步骤
全局
定义一个信号量
主线程
创建信号量(为触发状态)
创建线程
等待线程运行结束
关闭线程句柄
删除信号量
子线程中
使信号量进入为未触发状态
进行相关工作
使信号量进入触发状态
编码实现
#include
#include
#include
// 定义信号量
HANDLE hSemap;
unsigned int __stdcall ThreadFun1(PVOID lpParam)
{
//使信号量进入未触发状态
WaitForSingleObject(hSemap, INFINITE);
int number = (int)lpParam;
//获取当前线程id
DWORD threadId = GetCurrentThreadId();
while (number > 0) {
printf("thread id is %d, number is %d\n", threadId, number--);
Sleep(1000);
}
//使信号量进入触发状态
ReleaseSemaphore(hSemap, 1, NULL);
return 0;
}
unsigned int __stdcall ThreadFun2(PVOID lpParam)
{
//使信号量进入未触发状态
WaitForSingleObject(hSemap, INFINITE);
int number = (int)lpParam;
//获取当前线程id
DWORD threadId = GetCurrentThreadId();
while (number > 0) {
printf("thread id is %d, number is %d\n", threadId, number--);
Sleep(1000);
}
//使信号量进入触发状态
ReleaseSemaphore(hSemap, 1, NULL);
return 0;
}
unsigned int __stdcall ThreadFun3(PVOID lpParam)
{
//使信号量进入未触发状态
WaitForSingleObject(hSemap, INFINITE);
int number = (int)lpParam;
//获取当前线程id
DWORD threadId = GetCurrentThreadId();
while (number > 0) {
printf("thread id is %d, number is %d\n", threadId, number--);
Sleep(1000);
}
//使信号量进入触发状态
ReleaseSemaphore(hSemap, 1, NULL);
return 0;
}
int main()
{
unsigned ThreadID1 = 0;
unsigned ThreadID2 = 0;
unsigned ThreadID3 = 0;
// 创建触发状态的信号量
hSemap = CreateSemaphore(NULL, 1, 1, NULL);
//创建线程
HANDLE handle1 = (HANDLE)_beginthreadex(NULL, 0, ThreadFun1, (void*)5, 0, &ThreadID1);
HANDLE handle2 = (HANDLE)_beginthreadex(NULL, 0, ThreadFun2, (void*)5, 0, &ThreadID2);
HANDLE handle3 = (HANDLE)_beginthreadex(NULL, 0, ThreadFun3, (void*)5, 0, &ThreadID3);
printf("main function thread1 id is %d\n", ThreadID1);
printf("main function thread2 id is %d\n", ThreadID2);
printf("main function thread3 id is %d\n", ThreadID3);
//永久等待线程运行结束
WaitForSingleObject(handle1, INFINITE);
WaitForSingleObject(handle2, INFINITE);
WaitForSingleObject(handle3, INFINITE);
//关闭线程句柄
CloseHandle(handle1);
CloseHandle(handle2);
CloseHandle(handle3);
//删除信号量
CloseHandle(hSemap);
system("pause");
return 0;
}
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
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
运行结果
main function thread1 id is 25020
main function thread2 id is 33360
main function thread3 id is 20720
thread id is 25020, number is 5
thread id is 25020, number is 4
thread id is 25020, number is 3
thread id is 25020, number is 2
thread id is 25020, number is 1
thread id is 33360, number is 5
thread id is 33360, number is 4
thread id is 33360, number is 3
thread id is 33360, number is 2
thread id is 33360, number is 1
thread id is 20720, number is 5
thread id is 20720, number is 4
thread id is 20720, number is 3
thread id is 20720, number is 2
thread id is 20720, number is 1
请按任意键继续. . .
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
3、windows下的线程同步
上面介绍的四种方法都是实现线程互斥,接下来介绍线程同步,即在线程互斥基础上实现有序访问
3.1、信号量
信号量除了可以实现线程互斥,也可以实现线程同步
实现步骤
全局
定义多个信号量
主线程
创建信号量(一个为触发,其他为未触发)
创建线程
等待线程运行结束
关闭线程句柄
删除信号量
子线程中
使线程进入未触发状态
进行相关工作
使线程进入触发状态
编码实现
这里我们控制线程2先执行,再执行线程1,最后执行线程3
#include
#include
#include
// 定义信号量
HANDLE hSemap1;
HANDLE hSemap2;
HANDLE hSemap3;
unsigned int __stdcall ThreadFun1(PVOID lpParam)
{
//使信号量1进入未触发状态
WaitForSingleObject(hSemap1, INFINITE);
int number = (int)lpParam;
//获取当前线程id
DWORD threadId = GetCurrentThreadId();
while (number > 0) {
printf("thread id is %d, number is %d\n", threadId, number--);
Sleep(1000);
}
//使信号量3进入触发状态
ReleaseSemaphore(hSemap3, 1, NULL);
return 0;
}
unsigned int __stdcall ThreadFun2(PVOID lpParam)
{
//使信号量2进入未触发状态
WaitForSingleObject(hSemap2, INFINITE);
int number = (int)lpParam;
//获取当前线程id
DWORD threadId = GetCurrentThreadId();
while (number > 0) {
printf("thread id is %d, number is %d\n", threadId, number--);
Sleep(1000);
}
//使信号量1进入触发状态
ReleaseSemaphore(hSemap1, 1, NULL);
return 0;
}
unsigned int __stdcall ThreadFun3(PVOID lpParam)
{
//使信号量3进入未触发状态
WaitForSingleObject(hSemap3, INFINITE);
int number = (int)lpParam;
//获取当前线程id
DWORD threadId = GetCurrentThreadId();
while (number > 0) {
printf("thread id is %d, number is %d\n", threadId, number--);
Sleep(1000);
}
return 0;
}
int main()
{
unsigned ThreadID1 = 0;
unsigned ThreadID2 = 0;
unsigned ThreadID3 = 0;
// 设置信号量1的状态为未触发状态
hSemap1 = CreateSemaphore(NULL, 0, 1, NULL);
// 设置信号量2的状态为触发状态
hSemap2 = CreateSemaphore(NULL, 1, 1, NULL);
// 设置信号量3的状态为未触发状态
hSemap3 = CreateSemaphore(NULL, 0, 1, NULL);
//创建线程
HANDLE handle1 = (HANDLE)_beginthreadex(NULL, 0, ThreadFun1, (void*)5, 0, &ThreadID1);
HANDLE handle2 = (HANDLE)_beginthreadex(NULL, 0, ThreadFun2, (void*)5, 0, &ThreadID2);
HANDLE handle3 = (HANDLE)_beginthreadex(NULL, 0, ThreadFun3, (void*)5, 0, &ThreadID3);
printf("main function thread1 id is %d\n", ThreadID1);
printf("main function thread2 id is %d\n", ThreadID2);
printf("main function thread3 id is %d\n", ThreadID3);
//永久等待线程运行结束
WaitForSingleObject(handle1, INFINITE);
WaitForSingleObject(handle2, INFINITE);
WaitForSingleObject(handle3, INFINITE);
//关闭线程句柄
CloseHandle(handle1);
CloseHandle(handle2);
CloseHandle(handle3);
//删除信号量
CloseHandle(hSemap1);
CloseHandle(hSemap2);
CloseHandle(hSemap3);
system("pause");
return 0;
}
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
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
运行结果
可以看到,线程2先执行,然后线程1执行,最后线程3执行
main function thread1 id is 41360
main function thread2 id is 42024
main function thread3 id is 43380
thread id is 42024, number is 5
thread id is 42024, number is 4
thread id is 42024, number is 3
thread id is 42024, number is 2
thread id is 42024, number is 1
thread id is 41360, number is 5
thread id is 41360, number is 4
thread id is 41360, number is 3
thread id is 41360, number is 2
thread id is 41360, number is 1
thread id is 43380, number is 5
thread id is 43380, number is 4
thread id is 43380, number is 3
thread id is 43380, number is 2
thread id is 43380, number is 1
请按任意键继续. . .