1. 程式人生 > >並發共享數據

並發共享數據

lock 切分 日誌 返回值 形參 訪問 重啟 標準庫 開發

本文是關於並發共享數據的一些雜談, 就是一時回憶起這方面的東西然後記錄下來......

並發的競爭主要是涉及到數據的寫操作,如果所有的線程單單是讀操作,不會對共享數據產生競爭。

並發的訪問共享數據,競爭的bug會隨著時間和數據的規模越大而增大。很難排查,所以在開發並發性程序時,需要使用好並發的同步與互斥等復雜的方法來避免並發競爭,保護共享數據。

保護共享數據就是保護不變量被破壞的中間狀態只有一個線程訪問。

保護並發的方法:

  • 對數據進行某種保護機制(例如 互斥量),當某個線程訪問的時候,其他線程對該數據塊只有已完成或者未開始的狀態。
  • 通過把對共享數據的操作設計為原子操作,不切分割的狀態,讓不變量保持穩定的狀態。(無鎖編程
  • 還有一種是使用事務的方式去處理數據結構的更新(類似數據庫的事務提交),將需要做的操作存儲在日誌中,將之前的操作合為一步,再進行提交。當數據結構被另一個線程修改,後者處理已經重啟的情況下,提交就不會進行。(軟件事務內存

互斥量:
使用c++標準庫的互斥量,std::mutex,但是一般是使用具有RAII語法的std::lock_guard

使用互斥量時,設計接口時需要註意不要留下對數據的任何訪問能修改數據的能力,比如互斥量保護的代碼塊返回的是指針或者引用時,外部可能通過指針或引用來訪問或修改不變量,那麽就喪失了互斥量保護不變量的目的。
切勿將受保護數據的指針或引用傳遞到互斥所的作用域之外,無論是函數返回值,還是存儲在外部可見內存,或者以參數的形式傳遞到用戶提供的函數中

總的來說,並發編程時,註意成員函數的返回值和形參是否會傳出被互斥量保護數據的指針/引用,或傳入指針/引用來帶出被互斥量保護數據。

並發共享數據