題目:子線程循環 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"); }
讀者寫者問題
這也是一個非常經典的多線程題目,題目大意如下:有一個寫者很多讀者,多個讀者可以同時讀文件,但寫者在寫文件時不允許有讀者在讀文件,同樣有讀者讀時寫者也不能寫。
class rwlock { private: mutex _lock; condition_variable _wcon, _rcon; unsigned _writer, _reader; int _active; public: void read_lock() { unique_lock<mutex> lock(_lock); ++_reader; while (_active < 0 || _writer > 0) _rcon.wait(lock); --_reader; ++_active; } void write_lock() { unique_lock<mutex> lock(_lock); ++_writer; while (_active != 0) _wcon.wait(lock); --_writer; _active = -1; } void unlock() { unique_lock<mutex> lock(_lock); if (_active > 0) { --_active; if (_active == 0) _wcon.notify_one(); } else { _active = 0; if (_writer > 0) _wcon.notify_one(); else if (_reader > 0) _rcon.notify_all(); } } rwlock() :_writer(0), _reader(0), _active(0) { } }; void t1(rwlock* rwl) { while (1) { cout << "I want to write." << endl; rwl->write_lock(); cout << "writing..." << endl; this_thread::sleep_for(chrono::seconds(5)); rwl->unlock(); this_thread::sleep_for(chrono::seconds(5)); } } void t2(rwlock* rwl) { while (1) { cout << "t2-I want to read." << endl; rwl->read_lock(); cout << "t2-reading..." << endl; this_thread::sleep_for(chrono::seconds(1)); rwl->unlock(); } } void t3(rwlock* rwl) { while (1) { cout << "t3-I want to read." << endl; rwl->read_lock(); cout << "t3-reading..." << endl; this_thread::sleep_for(chrono::seconds(1)); rwl->unlock(); } } int main() { rwlock* rwl = new rwlock(); thread th1(t1, rwl); thread th2(t2, rwl); thread th3(t3, rwl); th1.join(); th2.join(); th3.join(); system("pause"); return 0; }
線程安全的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(); } };
題目:編寫程序完成如下功能:
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的時候退出
atomic<int> flag(0); void worker1(future<int> fut) {//線程1 printf("this is thread1\n"); flag = 1; fut.get();//線程1阻塞至線程2設置共享狀態 get等待異步操作結束並返回結果 printf("thread1 exit\n"); } void worker2(promise<int> prom) {//線程2 printf("this is thread2\n");//C++11的線程輸出cout沒有boost的好,還是會出現亂序,所以采用printf,有點不爽 flag = 2; prom.set_value(10);//線程2設置了共享狀態后,線程1才會被喚醒 printf("thread2 exit\n"); } //利用promise future來控制線程退出的次序 int main() { promise<int> prom; future<int> fut = prom.get_future(); thread one(worker1, move(fut));//注意future和promise不允許拷貝,但是具備move語義 thread two(worker2, move(prom)); while (flag.load() == 0);
///將本線程從調用線程中分離出來,允許本線程獨立執行 one.detach(); two.detach(); //exit(1);//主線程到這里退出 printf("main thread exit\n"); system("pause"); return 0; }
http://blog.csdn.net/liuxuejiang158blog/article/details/22300081