题目1:子线程循环 10 次,接着主线程循环 100 次,接着又回到子线程循环 10 次,接着再回到主线程又循环 100 次,如此循环50次,试写出代码
解答1:
#include <iostream>
#include <mutex>
#include <thread>
using namespace std;
const int count = 50;
int flag = 10;
std::mutex mtex;
void fun(const int num, const string &str) {
for (int i = 0; i < count; ++i) {
while (num != flag)
std::this_thread::yield();
mtex.lock();
for (int j = 0; j < num; ++j) {
cout << str << endl;
}
std::this_thread::sleep_for(std::chrono::seconds(1));
flag = (flag == 10 ? 100 : 10);
mtex.unlock();
}
}
int main(void) {
auto start = std::chrono::high_resolution_clock::now();
thread child(fun, 10, "child");
fun(100, "father");
child.join();
auto end = std::chrono::high_resolution_clock::now();
std::chrono::duration<double, std::milli> elapsed = end - start;
cout << elapsed.count() << endl;
return 0;
}
解答2
// 子线程循环 10 次,接着主线程循环 100 次,接着又回到子线程循环 10
// 次,接着再回到主线程又循环 100 次,如此循环50次,试写出代码
#include <condition_variable>
#include <iostream>
#include <mutex>
#include <thread>
using namespace std;
const int count = 50;
int flag = 10;
condition_variable cv;
std::mutex mtex;
void fun(const int num, const string &str) {
for (int i = 0; i < count; ++i) {
unique_lock<std::mutex> lk(mtex);
cv.wait(lk, [&] { return num == flag; });
for (int j = 0; j < num; ++j) {
cout << str << endl;
}
std::this_thread::sleep_for(std::chrono::seconds(1));
flag = (flag == 10 ? 100 : 10);
mtex.unlock();
cv.notify_one();
}
}
int main(void) {
auto start = std::chrono::high_resolution_clock::now();
thread child(fun, 10, "child");
fun(100, "father");
child.join();
auto end = std::chrono::high_resolution_clock::now();
std::chrono::duration<double, std::milli> elapsed = end - start;
cout << elapsed.count() << endl;
return 0;
}
题目2:编写一个程序,开启3个线程,这3个线程的ID分别为A、B、C,每个线程将自己的ID在屏幕上打印10遍,要求输出结果必须按ABC的顺序显示;如:ABCABC….依次递推
写法1
#include <iostream>
#include <thread>
#include <mutex>
using namespace std;
int main(void) {
std::mutex mtex;
int cnt = 0;
auto work = [&](char ch, int num) {
while(num--) {
while(ch != cnt + 'A') std::this_thread::yield();
std::unique_lock<std::mutex> lk(mtex);
cout << ch;
cnt = (cnt + 1) % 3;
lk.unlock();
}
};
thread t1(work, 'A', 10);
thread t2(work, 'B', 10);
work('C', 10);
t1.join();
t2.join();
return 0;
}
写法2
#include <iostream>
#include <thread>
#include <mutex>
#include <chrono>
#include <condition_variable>
using namespace std;
condition_variable cv;
std::mutex mtex;
int cnt = 0;
void work(char ch, int num) {
while(num--) {
std::this_thread::sleep_for(std::chrono::seconds(1));
unique_lock<std::mutex> lk(mtex);
cv.wait(lk, [&]{
return 'A' + cnt == ch;
});
cout << ch;
cnt = (cnt + 1) % 3;
lk.unlock();
cv.notify_one();
}
}
int main(void) {
thread t1(work, 'A', 10);
thread t2(work, 'B', 10);
work('C', 10);
t1.join();
t2.join();
return 0;
}
题目3:(google笔试题):有四个线程1、2、3、4。线程 1 的功能就是输出1,线程2的功能就是输出2,以此类推.........现在有四个文件ABCD。初始都为空。现要让四个文件呈如下格式:
A:1 2 3 4 1 2....
B:2 3 4 1 2 3....
C:3 4 1 2 3 4....
D:4 1 2 3 4 1....
#include <iostream>
#include <thread>
#include <mutex>
#include <fstream>
#include <condition_variable>
using namespace std;
const string filename = "D://code//c++//ac36";
condition_variable cv;
std::mutex mtex;
int vis[] = {4, 1, 2, 3};//四个文件上一次分别写入的值
ofstream f1(filename + "_A.txt");
ofstream f2(filename + "_B.txt");
ofstream f3(filename + "_C.txt");
ofstream f4(filename + "_D.txt");
ofstream *file[4];
void solve(const int x, int gg) {
while(gg--){
for(int i = 0; i < 4; ++i) {
std::unique_lock<std::mutex> lk(mtex);
if(x == 1) {
cv.wait(lk, [&]{
return vis[i] == 4;
});
(*file[i]) << 1;
vis[i] = 1;
lk.unlock();
cv.notify_all();
}else if(x == 2) {
cv.wait(lk, [&]{
return vis[i] == 1;
});
(*file[i]) << 2;
vis[i] = 2;
lk.unlock();
cv.notify_all();
}else if(x == 3) {
cv.wait(lk, [&]{
return vis[i] == 2;
});
(*file[i]) << 3;
vis[i] = 3;
lk.unlock();
cv.notify_all();
}else {
cv.wait(lk, [&]{
return vis[i] == 3;
});
(*file[i]) << 4;
vis[i] = 4;
lk.unlock();
cv.notify_all();
}
}
}
}
int main(void) {
file[0] = &f1;
file[1] = &f2;
file[2] = &f3;
file[3] = &f4;
thread t1(solve, 1, 10);
thread t2(solve, 2, 10);
thread t3(solve, 3, 10);
solve(4, 10);
t1.join();
t2.join();
t3.join();
for(int i = 0; i < 4; ++i) {
file[i]->close();
}
return 0;
}
题目4:有一个写者很多读者,多个读者可以同时读文件,但写者在写文件时不允许有读者在读文件,同样有读者读时写者也不能写
代码:
#include <iostream>
#include <thread>
#include <mutex>
#include <fstream>
#include <stdio.h>
#include <condition_variable>
using namespace std;
const string filename = "D://code//c++//ac36.txt";
std::condition_variable cv;
std::mutex mtx;
int cnt = 0;
ifstream in(filename);
ofstream out(filename, ios::app);
void write() {
char ch;
while(true) {
std::unique_lock<std::mutex> lk(mtx);
ch = getchar();
out << ch;
++cnt;
lk.unlock();
cv.notify_all();
}
}
void read() {
char ch;
while(true) {
std::unique_lock<std::mutex> lk(mtx);
cv.wait(lk, [&]{
return cnt > 0;
});
in >> ch;
cout << "cout: " << ch << endl;
--cnt;
}
}
int main(void) {
cnt = in.tellg();
std::thread tw(write);
std::thread tr1(read);
std::thread tr2(read);
std::thread tr3(read);
tw.join();
tr1.join();
tr2.join();
tr3.join();
in.close();
out.close();
return 0;
}
线程安全的 queue
STL 中的 queue 是非线程安全的,一个组合操作:front(); pop() 先读取队首元素然后删除队首元素,若是有多个线程执行这个组合操作的话,可能会发生执行序列交替执行,导致一些意想不到的行为。因此需要重新设计线程安全的 queue 的接口
#include <iostream>
#include <thread>
#include <mutex>
#include <queue>
#include <chrono>
#include <condition_variable>
using namespace std;
template <typename T>
class thread_safe_queue{
private:
std::condition_variable cv;
std::queue<T> que;
std::mutex mtx;
public:
thread_safe_queue() = default;
thread_safe_queue(const std::queue<T> q) : que(q) {}
thread_safe_queue(const thread_safe_queue &tsf) {
std::unique_lock<std::mutex> lk(mtx);
que = tsf.que;
}
~thread_safe_queue() = default;
void push(const T &value) {
std::unique_lock<std::mutex> lk(mtx);
que.push(value);
lk.unlock();
cv.notify_all();
}
T pop(void) {
std::unique_lock<std::mutex> lk(mtx);
cv.wait(lk, [&]{
return bool(!que.empty());
});
T value = que.front();
que.pop();
return value;
}
bool empty(void) {
std::unique_lock<std::mutex> lk(mtx);
return que.empty();
}
};
thread_safe_queue<int> q;
std::mutex mtx;
int main(void) {
auto push_value = [&]{
for(int i = 0; i < 100; ++i) {
q.push(i);
std::this_thread::sleep_for(std::chrono::seconds(1));
}
};
auto pop_value = [&]{
while(1) {
while(!q.empty()) {
std::unique_lock<std::mutex> lk(mtx);
cout << q.pop() << '\n';
}
}
};
thread push_thread1(push_value);
thread pop_thread1(pop_value);
thread pop_thread2(pop_value);
thread pop_thread3(pop_value);
push_thread1.join();
pop_thread1.join();
pop_thread2.join();
pop_thread3.join();
return 0;
}
题目6:编写程序完成如下功能:
1)有一int型全局变量g_Flag初始值为0
2) 在主线称中起动线程1,打印“this is thread1”,并将g_Flag设置为1
3) 在主线称中启动线程2,打印“this is thread2”,并将g_Flag设置为2
4) 线程序1需要在线程2退出后才能退出
5) 主线程在检测到g_Flag从1变为2,或者从2变为1的时候退出
代码1:
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
using namespace std;
std::condition_variable cv;
std::mutex metx;
int g_Flag = 0;
int cnt = 0;
bool flag = false;
int main(void) {
thread t1([&]{
std::unique_lock<std::mutex> lk(metx);
cout << "this is thread1\n";
g_Flag = 1;
++cnt;
cv.wait(lk, [&]{{
return flag;
}});
cout << "thread1 exit\n";
});
thread t2([&]{
std::unique_lock<std::mutex> lk(metx);
cout << "this is thread2\n";
g_Flag = 2;
cnt++;
flag = true;
cv.notify_all();
cout << "thread2 exit\n";
});
t1.detach();//分离线程
t2.detach();
std::unique_lock<std::mutex> lc(metx);
cv.wait(lc, [&]{
return cnt >= 2;
});
cout << "main thread exit\n";
return 0;
}
#include <iostream>
#include <thread>
#include <mutex>
#include <atomic>
#include <future>
using namespace std;
atomic<int> g_Flag(0), cnt(0);
void thread1(std::future<int> fu) {
cout << "this is thread1\n";
g_Flag = 1;
++cnt;
fu.get();//线程1阻塞至线程2设置共享状态, get等待异步操作结束并返回结果
cout << "thread1 exit\n";
}
void thread2(std::promise<int> pro) {
cout << "this is thread2\n";
g_Flag = 2;
++cnt;
cout << "thread2 exit\n";
pro.set_value(1);//设置共享值
}
int main(void) {
std::promise<int> prom;//创建一个promise对象
std::future<int> fu = prom.get_future();//获得promise内部的future,fut将和prom共享prom中的共享状态
std::thread t1(thread1, std::move(fu));//通过fut在线程1中得到线程2的状态
std::thread t2(thread2, std::move(prom));//通过prom设置线程2中的共享状态
t1.detach();
t2.detach();
while(cnt < 2);
cout << "main thread exit\n";
return 0;
}