首页 > 代码库 > c++多线程编程:常见面试题
c++多线程编程:常见面试题
题目:子线程循环 10 次,接着主线程循环 100 次,接着又回到子线程循环 10 次,接着再回到主线程又循环 100 次,如此循环50次,试写出代码
子线程与主线程必有一个满足条件(flag == num),不满足条件的那个线程不可能获取unique_lock(会在wait中释放),只有满足条件的线程才能获取锁,执行程序
mutex m;//保护条件的互斥访问condition_variable cond;//条件变量int flag = 10;//条件void fun(int num) { for (int i = 0; i<50; i++) { unique_lock<mutex> lk(m);//A unique lock is an object that manages a mutex object with unique ownership in both states: locked and unlocked. while (flag != num) cond.wait(lk);//在调用wait时会执行lk.unlock() for (int j = 0; j<num; j++) cout << j << " "; cout << endl; flag = (num == 10) ? 100 : 10; cond.notify_one();//被阻塞的线程唤醒后lk.lock()恢复在调用wait前的状态 }}int main() { thread child(fun, 10); fun(100); child.join(); system("pause"); return 0;}
题目:编写一个程序,开启3个线程,这3个线程的ID分别为A、B、C,每个线程将自己的ID在屏幕上打印10遍,要求输出结果必须按ABC的顺序显示;如:ABCABC….依次递推。
mutex m;condition_variable cond;int loop = 10;int flag = 0;void func(int id){ for (int i = 0; i < loop; ++i) { unique_lock<mutex> lk(m); while (flag != id) cond.wait(lk); cout << static_cast<char>(‘A‘ + id) << " "; flag = (flag + 1) % 3; cond.notify_all(); }}void main(){ thread A(func, 0); thread B(func, 1); func(2); cout << endl; A.join(); B.join(); system("pause");}
题目(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....
mutex m;condition_variable cond;int loop = 10;int flag;void func(int num){ for (int i = 0; i < loop; ++i) { unique_lock<mutex> lk(m); while (num != flag) cond.wait(lk); cout << num + 1 << " "; flag = (flag + 1) % 4; cond.notify_all(); }}void main(int argc,char *argv[]){ flag = atoi(argv[1]); thread one(func, 1); thread two(func, 2); thread three(func, 3); func(0); one.join(); two.join(); three.join(); cout << endl; system("pause");}
读者写者问题
这也是一个非常经典的多线程题目,题目大意如下:有一个写者很多读者,多个读者可以同时读文件,但写者在写文件时不允许有读者在读文件,同样有读者读时写者也不能写。
这里采用copy on write(写时拷贝)实现,主要要理解智能指针std::shared_ptr的用法,用访问vector替代题目中的文件,代码如下:
http://c.biancheng.net/cpp/html/2601.html
int readerNum = 0;mutex m;mutex rw;void writer(){ rw.lock(); cout << "i am writing" << endl; rw.unlock();}void reader(){ m.lock(); if (readerNum == 0) rw.lock(); readerNum++; m.unlock(); cout << "i am reading" << endl; m.lock(); readerNum--; if (readerNum == 0) rw.unlock(); m.unlock();}void main() { thread wr1(writer); thread rd1(reader); wr1.join(); rd1.join(); system("pause");}
线程安全的queue
STL中的queue是非线程安全的,一个组合操作:front(); pop()先读取队首元素然后删除队首元素,若是有多个线程执行这个组合操作的话,可能会发生执行序列交替执行,导致一些意想不到的行为。因此需要重新设计线程安全的queue的接口。
template<typename T>class threadsafe_queue{private: mutable std::mutex mut; std::queue<T> data_queue; std::condition_variable data_cond;public: threadsafe_queue() {} threadsafe_queue(threadsafe_queue const& other) { std::lock_guard<std::mutex> lk(other.mut); data_queue = other.data_queue; } void push(T new_value)//入队操作 { std::lock_guard<std::mutex> lk(mut); data_queue.push(new_value); data_cond.notify_one(); } void wait_and_pop(T& value)//直到有元素可以删除为止 { std::unique_lock<std::mutex> lk(mut); data_cond.wait(lk, [this] {return !data_queue.empty(); }); value = data_queue.front(); data_queue.pop(); } std::shared_ptr<T> wait_and_pop() { std::unique_lock<std::mutex> lk(mut); data_cond.wait(lk, [this] {return !data_queue.empty(); }); std::shared_ptr<T> res(std::make_shared<T>(data_queue.front())); data_queue.pop(); return res; } bool try_pop(T& value)//不管有没有队首元素直接返回 { std::lock_guard<std::mutex> lk(mut); if (data_queue.empty()) return false; value = data_queue.front(); data_queue.pop(); return true; } std::shared_ptr<T> try_pop() { std::lock_guard<std::mutex> lk(mut); if (data_queue.empty()) return std::shared_ptr<T>(); std::shared_ptr<T> res(std::make_shared<T>(data_queue.front())); data_queue.pop(); return res; } bool empty() const { std::lock_guard<std::mutex> lk(mut); return data_queue.empty(); }};
c++多线程编程:常见面试题