C++多线程编程二
2024-08-31 07:05:53
1. 死锁与解锁:
#include <iostream>
#include <thread>
#include <mutex> using namespace std; //thread引用类型函数,模板,避免类型转换,尽量指针,引用
//锁住一个变量之后,尽快操作完解锁,不要再锁,否则互锁
#define COUNT 100000
mutex g_mutex1, g_mutex2;//互斥量 void add1(int *p1, int *p2)
{
for (int i = ; i < COUNT; i++)
{
/*g_mutex1.lock();
p1++;
g_mutex2.lock();
p2++;
g_mutex1.unlock();
g_mutex2.unlock();*/ g_mutex1.lock();
(*p1)++;
g_mutex1.unlock(); g_mutex2.lock();
(*p2)++;
g_mutex2.unlock();
}
}
void add2(int *p1, int *p2)
{
for (int i = ; i < COUNT; i++)
{
/*g_mutex2.lock();
g_mutex1.lock();
p1++;
g_mutex1.unlock();
p2++;
g_mutex2.unlock();*/ g_mutex2.lock();
(*p2)++;
g_mutex2.unlock(); g_mutex1.lock();
(*p1)++;
g_mutex1.unlock();
}
} void main()
{
int a = ;
int b = ; thread th1(add1, &a, &b);
thread th2(add2, &a, &b); th1.join();
th2.join(); while ()
{
cout << a << endl;
cout << b << endl;
this_thread::sleep_for(chrono::seconds()); } cin.get();
}
2. 迅雷面试题:
编写一个程序,开启3个线程,这3个线程的ID分别为A、B、C,每个线程将自己的ID在屏幕上打印10遍,
要求输出结果必须按ABC的顺序显示。如:ABCABC...,依次递推。
【参考答案】
//编写一个程序,开启3个线程,这3个线程的ID分别为A、B、C,每个线程将自己的ID在屏幕上打印10遍,
//要求输出结果必须按ABC的顺序显示。如:ABCABC...,依次递推。
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable> using namespace std; int LOOP = ; //循环次数
int flag = ; //标识符 012012012012
mutex m;
condition_variable cv; void fun(int id)
{
for (int i = ; i < LOOP; i++)
{
unique_lock<mutex> ulk(m); //设定锁定
while ((id-) != flag)
{
cv.wait(ulk); //不是该出现的场合,就等待
}
cout << (char)id; //转换id flag = (flag + ) % ; //012,012,012,...
cv.notify_all(); //通知全部
}
} void main()
{
thread t1(fun, );
thread t2(fun, );
thread t3(fun, ); t1.join();
t2.join();
t3.join(); cin.get();
}
运行结果:
【分析】若题目变为:4个线程,输出结果要求为: ABCDABCDABCD...又该如何做呢?
//编写一个程序,开启3个线程,这3个线程的ID分别为A、B、C,每个线程将自己的ID在屏幕上打印10遍,
//要求输出结果必须按ABC的顺序显示。如:ABCABC...,依次递推。 #include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable> using namespace std; int LOOP = ; //循环次数
int flag = ; //标识符 012012012012
mutex m;
condition_variable cv; void fun(int id)
{
for (int i = ; i < LOOP; i++)
{
unique_lock<mutex> ulk(m); //设定锁定
while ((id-) != flag)
{
cv.wait(ulk); //不是该出现的场合,就等待
}
cout << (char)id; //转换id flag = (flag + ) % ; //012,012,012,...
cv.notify_all(); //通知全部
}
} void main()
{
thread t1(fun, );
thread t2(fun, );
thread t3(fun, );
thread t4(fun, ); t1.join();
t2.join();
t3.join();
t4.join(); cin.get();
}
运行结果:
3. 思考:上题中若变为开启5个线程,ID分别为1,2,3,4,5,每个线程将自己的ID在屏幕上打印10遍,要求输出结果为:12345,54321,12345,54321,...依此类推。
4. 线程交换 swap:
#include <iostream>
#include <thread>
using namespace std; void main()
{
thread t1([]() {cout << "ZhangShan"<<endl; });
thread t2([]() {cout << "LiSi"<<endl; }); cout << "t1.get_id():" << t1.get_id() << " t2.get_id():" << t2.get_id() << endl; swap(t1, t2); //交换句柄 cout << "t1.get_id():" << t1.get_id() << " t2.get_id():" << t2.get_id() << endl; t1.join();
t2.join(); cin.get();
}
5. 线程移动 move:
#include <iostream>
#include <thread>
#include <cstdlib> using namespace std; void main()
{
thread t1([]()
{
int i = ;
while ()
{
i++;
if (i > )
{
break;
}
}
cout << i << endl;
system("pause");
}); cout << "t1:" << t1.get_id() << endl; //6872
//t1.join();
thread t2 = move(t1);//线程移动,t2具备了t1的属性,t1挂了
cout << "t1:" << t1.get_id() << endl; //
cout << "t2:" << t2.get_id() << endl; // t2.join(); cin.get();
}
运行结果:
6. 线程自动加解锁:
#include <iostream>
#include <thread>
#include <mutex> using namespace std; #define N 10000000
mutex g_mutex;//全局互斥量 void add(int *p)
{
for (int i = ; i < N; i++)
{
unique_lock<mutex> ulk(g_mutex);
//没有mutex所有权,自动加锁自动解锁,根据块语句锁定
//根据mutex属性来决定,是否可以加锁 //lock_guard<mutex> lgd(g_mutex);
//拥有mutex所有权,自动加锁自动解锁
//读取mutex失败的情况下就会一直等待
(*p)++;
}
} void main()
{
int a = ; thread t1(add, &a);
thread t2(add, &a); t1.join();
t2.join(); cout << a << endl; cin.get();
}
7. 线程等待固定时间:
#include <iostream>
#include <thread>
#include <chrono>
#include <mutex>
#include <condition_variable>
#include <cstdlib>
#include <ctime> using namespace std; condition_variable cv;
mutex m;
bool done=false; void run()
{
auto start = chrono::high_resolution_clock::now(); //当前时间
auto end = start + chrono::seconds(); unique_lock<mutex> ulk(m);
while (!done)
{
if (cv.wait_until(ulk, end) == cv_status::timeout)//超时
{
done = true;
break;
}
}
//this_thread::sleep_until(end); system("pause");
} void main1601()
{
thread th(run); cin.get();
} void main()
{
time_t t1, t2;
auto start = chrono::high_resolution_clock::now(); //当前时间
t1 = time(&t1); double db = ;
for (int i = ; i < ; i++)
{
db += i;
} auto end = chrono::high_resolution_clock::now(); //当前时间
t2 = time(&t2); cout << (end - start).count() << endl; //10^-9秒(ns)
cout << difftime(t2, t1) << endl; cin.get();
}
8. 多线程实现生产者、消费者:
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <array>
#include <vector> using namespace std; mutex m;
condition_variable isfull, isempty;//处理两种情况
bool flag = true;//标志,消费完了就退出
vector<int> myint();//开辟10个元素 void produce(int num) //生产
{
for (int i = ; i < num; i++)
{
unique_lock<mutex> lk(m); //锁定
while (myint.size()>=)
{
isempty.wait(lk); //满了一直等待
} myint.push_back(i);//插入
cout << "生产" << i << endl;
isfull.notify_all();//通知消费者 } this_thread::sleep_for(chrono::seconds());//休眠5秒 flag = false;
} void consume() //消费
{
while (flag)
{
unique_lock<mutex> lk(m); //锁定
while (myint.size()==)
{
isfull.wait(lk);//等待
} if (flag)
{
cout << "消费" << myint[myint.size() - ] << " " << this_thread::get_id() << endl;
myint.pop_back();//剔除最后一个 isempty.notify_all();//通知生产者继续生产
}
}
} void main()
{
thread t1(consume); //消费者
thread t2(consume);
thread t3(consume); //produce(100);
thread s1(produce,);//消费者
thread s2(produce,); t1.join();
t2.join();
t3.join(); cin.get();
}
最新文章
- javaee中的中文乱码处理
- Sublime Text 有哪些使用技巧
- URI, URL, and URN
- Ror初学笔记
- js糟粕
- 总结一下ASP.NET MVC 网站的部署问题
- 将一个字典内的内value转换为集合:返回一个数组,此数组中包含输入字典的键值对中的数组的所有元素(为NSArray添加category)
- Jmeter+Badboy实战经验三 Jmeter关联相关知识
- Android开发技巧——自定义控件之使用style
- MyBatis 3源码解析(三)
- 数据库基础 RDBMS、NoSQL
- python之路(十一)-socke开发
- linux 命令之 dmidecode
- 性能测试工具--SIEGE安装及使用简介 siege压力测试
- Redis入门到高可用(十七)—— 持久化开发运维常见问题
- .NET接入UnionPay银联支付(一)手机wap支付
- 【转】oracle CONNECT BY PRIOR叶子节点查找根节点
- Vue.Js添加自定义插件
- Spring Boot 应用系列 4 -- Spring Boot 2 整合log4j2
- nginx 日志模块