C++线程类thread、线程互斥(模拟卖票)和同步通信(生产者消费者模型)

C++ 11线程类thread

C++11提供线程类thread之前,windows上调用CreateThread创建线程,linux上调用pthread_create创建线程,直接调用系统API函数,编写的程序无法做到跨平台编译运行。

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
#include <iostream>
#include <thread>

void ThreadProc1()
{
std::cout << "thread 1 run begin\n";
std::this_thread::sleep_for(std::chrono::seconds(2));
std::cout << "thread 1 - 2秒唤醒 run end\n";
}

void ThreadProc2(int& val, std::string& str)
{
std::cout << "thread 2 run begin\n";
std::this_thread::sleep_for(std::chrono::seconds(4));
std::cout << "thread 2 - 4秒唤醒\n";
std::cout << "value: " << val << " str: " << str << std::endl;
std::cout << "thread 2 run end\n";
}

int main()
{
std::cout << "main thread run begin\n";
std::thread t1(ThreadProc1);
int val = 5;
std::string str = "pattern";
std::thread t2(ThreadProc2, std::ref(val), std::ref(str));

t1.join();
t2.join();
std::cout << "main thread run end\n";
return 0;
}

运行结果:

1
2
3
4
5
6
7
8
main thread run begin
thread 1 run begin
thread 2 run begin
thread 1 - 2秒唤醒 run end
thread 2 - 4秒唤醒
value: 5 str: pattern
thread 2 run end
main thread run end

线程互斥(模拟卖票)

多线程环境要保证临界区资源的互斥访问

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
#include <iostream>
#include <thread>
#include <mutex>

// volatile 关键字修饰,volatile 指出变量是随时可能发生变化的
// 使用 volatile 声明的变量的值的时候,系统总是重新从它所在的内存读取数据,
// 即使它前面的指令刚刚从该处读取过数据。
volatile int tickets = 100;
std::mutex mtx;

// 线程函数
void sellTicketTask(std::string name)
{
while (tickets > 0)
{
// 获取互斥锁资源
mtx.lock();
if (tickets > 0)
{
std::cout << name << " 售卖第" << tickets << "张票" << std::endl;
tickets--;
}
// 释放互斥锁资源
mtx.unlock();

// 每卖出一张票,睡眠100ms,让每个窗口都有机会卖票
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
}

// 模拟车站窗口卖票
int main()
{
// 创建三个模拟窗口卖票线程
std::thread t1(sellTicketTask, "车票窗口一");
std::thread t2(sellTicketTask, "车票窗口二");
std::thread t3(sellTicketTask, "车票窗口三");

// 等待三个线程执行完成
t1.join();
t2.join();
t3.join();

return 0;
}

线程同步通信(生产者消费者模型)

C++11 线程库提供条件变量condition_variable,用于解决线程间的同步通信问题。

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
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <vector>

std::mutex mtx;
std::condition_variable cv;
std::vector<int> vec;

// 生产者线程函数
void producer()
{
for (int i = 0; i < 20; ++i) {
std::unique_lock<std::mutex> lock(mtx);
while (!vec.empty()) {
cv.wait(lock);
}
vec.push_back(i);
std::cout << "生产者生产商品 " << i << std::endl;
cv.notify_all();

std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
}
// 消费者线程函数
void consumer()
{
for (int i = 0; i < 20; ++i) {
std::unique_lock<std::mutex> lock(mtx);
while (vec.empty()) {
cv.wait(lock);
}
std::cout << "消费者消费商品 " << vec.back() << std::endl;
vec.pop_back();
cv.notify_all();

std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
}

int main()
{
// 创建生产者和消费者线程
std::thread t1(producer);
std::thread t2(consumer);

// main主线程等待所有子线程执行完
t1.join();
t2.join();

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
生产者生产商品 0
消费者消费商品 0
生产者生产商品 1
消费者消费商品 1
生产者生产商品 2
消费者消费商品 2
生产者生产商品 3
消费者消费商品 3
生产者生产商品 4
消费者消费商品 4
生产者生产商品 5
消费者消费商品 5
生产者生产商品 6
消费者消费商品 6
生产者生产商品 7
消费者消费商品 7
生产者生产商品 8
消费者消费商品 8
生产者生产商品 9
消费者消费商品 9
生产者生产商品 10
消费者消费商品 10
生产者生产商品 11
消费者消费商品 11
生产者生产商品 12
消费者消费商品 12
生产者生产商品 13
消费者消费商品 13
生产者生产商品 14
消费者消费商品 14
生产者生产商品 15
消费者消费商品 15
生产者生产商品 16
消费者消费商品 16
生产者生产商品 17
消费者消费商品 17
生产者生产商品 18
消费者消费商品 18
生产者生产商品 19
消费者消费商品 19

https://blog.csdn.net/QIANGWEIYUAN/article/details/88792621