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();
}

最新文章

  1. javaee中的中文乱码处理
  2. Sublime Text 有哪些使用技巧
  3. URI, URL, and URN
  4. Ror初学笔记
  5. js糟粕
  6. 总结一下ASP.NET MVC 网站的部署问题
  7. 将一个字典内的内value转换为集合:返回一个数组,此数组中包含输入字典的键值对中的数组的所有元素(为NSArray添加category)
  8. Jmeter+Badboy实战经验三 Jmeter关联相关知识
  9. Android开发技巧——自定义控件之使用style
  10. MyBatis 3源码解析(三)
  11. 数据库基础 RDBMS、NoSQL
  12. python之路(十一)-socke开发
  13. linux 命令之 dmidecode
  14. 性能测试工具--SIEGE安装及使用简介 siege压力测试
  15. Redis入门到高可用(十七)—— 持久化开发运维常见问题
  16. .NET接入UnionPay银联支付(一)手机wap支付
  17. 【转】oracle CONNECT BY PRIOR叶子节点查找根节点
  18. Vue.Js添加自定义插件
  19. Spring Boot 应用系列 4 -- Spring Boot 2 整合log4j2
  20. nginx 日志模块

热门文章

  1. 发现ramnit样本一枚
  2. Golang之实现一个负载均衡算法(随机,轮询)
  3. 文字如何实现完美UI?文本排版设计告诉你
  4. 电商商品规则属性sku 工具类
  5. Oracle查看字符集
  6. os.path等os模块函数
  7. swoole多进程操作
  8. Haodoop RPC解析
  9. linux每天一小步---mkdir命令详解
  10. Layout布局源码浅析之——FrameLayout