多執行緒基礎(單讀、單寫、迴圈佇列、無鎖、lockfree)
阿新 • • 發佈:2019-02-08
有了前面執行緒建立和迴圈佇列的基礎,我們再來看一個單度、單寫利用迴圈佇列的例子,程式碼如下:
#include <stdio.h> #include <pthread.h> #include <string> #include "circular_queue.h" class ThreadBase { public: virtual ~ThreadBase() {} void SetMessage(const char* message) { message_ = message; } void Start() { pthread_create(&thread_id_, NULL, Hook, this); } void* Join() { void* ret = NULL; pthread_join(thread_id_, &ret); return ret; } virtual void Run() { printf("%s\n", message_.c_str()); } private: static void* Hook(void* object) { ThreadBase* thread_base= static_cast<ThreadBase*>(object); thread_base->Run(); } pthread_t thread_id_; std::string message_; }; class ThreadReader : public ThreadBase { public: ThreadReader(CircularQueue<int>* queue) : queue_(queue), write_finish_(false) {} virtual void Run() { int element; while (!write_finish_) { if (queue_->Pop(&element)) { printf("read:%d\n",element); } } while (queue_->Pop(&element)) { printf("read:%d\n", element); } } void NotifyWriteFinish() { write_finish_ = true; } private: CircularQueue<int>* queue_; bool write_finish_; }; class ThreadWriter : public ThreadBase { public: ThreadWriter(CircularQueue<int>* queue, ThreadReader* reader) : queue_(queue), reader_(reader) {} virtual void Run() { int index = 0; while(index < 10000) { if (queue_->Push(index)) { index++; } } reader_->NotifyWriteFinish(); } private: CircularQueue<int>* queue_; ThreadReader* reader_; }; int main(int argc, char** argv) { CircularQueue<int> queue(100); ThreadReader reader(&queue); ThreadWriter writer(&queue, &reader); reader.Start(); writer.Start(); reader.Join(); writer.Join(); }
寫執行緒不間斷寫入資料,寫入完成後會通知讀執行緒已經寫完,讀執行緒持續讀取資料,如果得到通知後,將緩衝區中的資料再全部讀出後,退出。
參考文獻:
《程式設計之美》中1.10 雙執行緒高效下載,但程式設計之美中使用了semaphore,本例子不需要使用semaphore,效率更好。
《系統程式設計師成長計劃》4.5無鎖資料結構