第5章 基礎概念記憶體模型有2個觀點,儲存物件的觀點 和訪問物件順序觀點。這裡我們討論是訪問物件順序。問題來了,有幾個方法記憶體的順序?6Listing 5.2 Reading and writing variables from different threads
#include <vector>#include <atomic>#include <iostream> std::vector<int> data;std::atomic<bool> data_ready(false);void reader_thread(){ while(!data_ready.load()) { std::this_thread::sleep(std::chrono::milliseconds(1)); } std::cout<<”The answer=”<<data[0]<<”\n”;}void writer_thread(){ data.push_back(42); data_ready=true;}//程式碼不是很準確:
Listing 5.5 Relaxed operations have few ordering requirements#include <atomic>#include <thread>#include <assert.h>std::atomic<bool> x,y;std::atomic<int> z;void write_x_then_y(){ x.store(true,std::memory_order_relaxed); y.store(true,std::memory_order_relaxed); //控制順序}void read_y_then_x(){ while(!y.load(std::memory_order_relaxed)); if(x.load(std::memory_order_relaxed)) ++z;}int main() { x=false; y=false; z=0; std::thread a(write_x_then_y); std::thread b(read_y_then_x); a.join(); b.join(); assert(z.load()!=0);}
Concurrency and the C++ Memory Model(來自影片)
cpu訪問
5還是0 volatie 關鍵字可以嗎
順序一致:
無鎖讀寫順序遍歷讀取和=操作。為什麼變成這個設計一個無鎖的棧,需要採用什麼結構儲存:atomic 扮演什麼角色連結串列插入操作 透過cas保證執行緒安全pic 3
透過pic3 發現幾個要點
假如是庫的作者,我返回地址時候,返回share_ptr 型別。問題來了,share_ptr 使用場景是?我作為容器,肯定多次被訪問,其他auto_ptr 肯定,複製導致原來不能使用。必須使用share_ptr ,pop記錄時候,while 與cas相結合。判斷是否被修改。這裡神奇地方old_head 每次都可能發生改變。升級:資料結構中的 head,竟然可以不用automic 修改,template<typename T>class lock_free_stack{private:struct node { std::shared_ptr<T> data; std::shared_ptr<node> next; node(T const& data_): data(std::make_shared<T>(data_)) {}}; std::shared_ptr<node> head;public: void push(T const& data) { std::shared_ptr<node> const new_node=std::make_shared<node>(data); new_node->next=std::atomic_load(&head); while(!std::atomic_compare_exchange_weak(&head, &new_node->next,new_node)); } std::shared_ptr<T> pop() { std::shared_ptr<node> old_head=std::atomic_load(&head); while(old_head && !std::atomic_compare_exchange_weak(&head, &old_head,std::atomic_load(&old_head->next))); if(old_head) { std::atomic_store(&old_head->next,std::shared_ptr<node>()); return old_head->data; } return std::shared_ptr<T>(); } ~lock_free_stack(){ while(pop());}};
Writing a thread-safe queue without locksA single-producer, single-consumer lock-free queuetemplate<typename T>class lock_free_queue{private:struct node { std::shared_ptr<T> data; node* next; node(): next(nullptr) {}};std::atomic<node*> head;std::atomic<node*> tail;node* pop_head(){ node* const old_head=head.load(); if(old_head==tail.load()) { return nullptr; } head.store(old_head->next); return old_head; }public: lock_free_queue(): head(new node),tail(head.load()) {} lock_free_queue(const lock_free_queue& other)=delete; lock_free_queue& operator=(const lock_free_queue& other)=delete; ~lock_free_queue() { while(node* const old_head=head.load()) { head.store(old_head->next); delete old_head; }}std::shared_ptr<T> pop(){ node* old_head=pop_head(); if(!old_head) { return std::shared_ptr<T>(); } std::shared_ptr<T> const res(old_head->data); delete old_head; return res;} //這裡沒考慮執行緒安全。
最新評論