Synchronization 进程锁
- Boost.Interprocess允許多個進程同時使用共享內(nèi)存。因為共享內(nèi)存從定義上來說是進程間共享的,所以Boost.Interprocess需要支持某種同步。
- 想到同步,我們會想到C++11標準庫中的類或Boost.Thread。但是這些類只能用來同步同一進程內(nèi)的線程,它們不支持不同進程的同步。不過,由于兩種情況下面臨的挑戰(zhàn)是一樣的,所以概念也是一樣的。
- 在多線程應用程序中,同步對象(如mutexes和條件變量)駐留在同一個地址空間中,因此所有線程都可以使用,而共享內(nèi)存的挑戰(zhàn)是,獨立的進程需要共享這些對象。例如,如果一個進程創(chuàng)建了一個mutex,那么它就需要以某種方式從另一個進程中訪問。
- Boost.Interprocess提供了兩種同步對象:匿名對象直接存儲在共享內(nèi)存中,這使得它們對所有進程自動可用。命名對象由操作系統(tǒng)管理,不存儲在共享內(nèi)存中,可以通過名稱從程序中引用(named_mutex)。
Example 33.12. Using a named mutex with boost::interprocess::named_mutex
#include <boost/interprocess/managed_shared_memory.hpp> #include <boost/interprocess/sync/named_mutex.hpp> #include <iostream>using namespace boost::interprocess;int main() {managed_shared_memory managed_shm{open_or_create, "shm", 1024};int *i = managed_shm.find_or_construct<int>("Integer")();named_mutex named_mtx{open_or_create, "mtx"};named_mtx.lock();++(*i);std::cout << *i << '\n';named_mtx.unlock(); }- Example?33.12?creates and uses a named mutex using the class?boost::interprocess::named_mutex, which is defined in?boost/interprocess/sync/named_mutex.hpp.
- boost::interprocess::named_mutex的構(gòu)造函數(shù)期望得到一個參數(shù),指定是否應該創(chuàng)建或打開mutex,以及mutex的名稱。每個知道這個名字的進程都可以打開同一個mutex。要訪問共享內(nèi)存中的數(shù)據(jù),程序需要通過調(diào)用成員函數(shù)lock()來獲得mutex的所有權(quán)。由于mutexes一次只能由一個進程擁有,所以另一個進程可能需要等待,直到mutex被unlock()釋放。一旦一個進程擁有了一個mutex的所有權(quán),它就擁有了對mutex所保護的資源的獨占性訪問權(quán)。在示例33.12中,資源是一個類型為int的變量,它被遞增并寫入標準輸出流。
- 如果示例程序被多次啟動,每個實例都會打印一個比前一個值遞增1的值。由于有了mutex,不同進程之間對共享內(nèi)存和變量本身的訪問是同步的。
Example?33.13.?Using an anonymous mutex with?interprocess_mutex
#include <boost/interprocess/managed_shared_memory.hpp> #include <boost/interprocess/sync/interprocess_mutex.hpp> #include <iostream>using namespace boost::interprocess;int main() {managed_shared_memory managed_shm{open_or_create, "shm", 1024};int *i = managed_shm.find_or_construct<int>("Integer")();interprocess_mutex *mtx =managed_shm.find_or_construct<interprocess_mutex>("mtx")();mtx->lock();++(*i);std::cout << *i << '\n';mtx->unlock(); }- Example?33.13?uses an anonymous mutex of type?boost::interprocess::interprocess_mutex, which is defined in?boost/interprocess/sync/interprocess_mutex.hpp. In order for the mutex to be accessible for all processes, it is stored in the shared memory.?
-
例33.13的行為與前一個完全相同。唯一不同的是mutex,它現(xiàn)在直接存儲在共享內(nèi)存中。這可以通過類 boost::interprocess::managed_shared_memory 中的成員函數(shù) construct() 或 find_or_construct() 來實現(xiàn)。除了lock(),boost::interprocess::named_mutex和boost::interprocess::interprocess_mutex都提供了成員函數(shù)try_lock()和timed_lock()。它們的行為與標準庫和Boost.Thread中的對應函數(shù)完全相同。如果需要遞歸互斥,Boost.Interprocess提供了兩個類:boost::interprocess::named_recursive_mutex和boost::interprocess::interprocess_recursive_mutex。
-
互斥保證了對共享資源的獨占訪問,而條件變量則控制了誰在什么時候擁有獨占訪問權(quán)。一般來說,Boost.Interprocess提供的條件變量與C++11標準庫和Boost.Thread提供的條件變量的工作原理類似。它們具有類似的接口,這使得這些庫的用戶在Boost.Interprocess中使用這些變量時,會立即感到賓至如歸。
Example?33.14.?Using a named condition with?boost::interprocess::named_condition
#include <boost/interprocess/managed_shared_memory.hpp> #include <boost/interprocess/sync/named_mutex.hpp> #include <boost/interprocess/sync/named_condition.hpp> #include <boost/interprocess/sync/scoped_lock.hpp> #include <iostream>using namespace boost::interprocess;int main() {managed_shared_memory managed_shm{open_or_create, "shm", 1024};int *i = managed_shm.find_or_construct<int>("Integer")(0);named_mutex named_mtx{open_or_create, "mtx"};named_condition named_cnd{open_or_create, "cnd"};scoped_lock<named_mutex> lock{named_mtx};while (*i < 10){if (*i % 2 == 0){++(*i);named_cnd.notify_all();named_cnd.wait(lock);}else{std::cout << *i << std::endl;++(*i);named_cnd.notify_all();named_cnd.wait(lock);}}named_cnd.notify_all();shared_memory_object::remove("shm");named_mutex::remove("mtx");named_condition::remove("cnd"); }- Example?33.14?uses a condition variable of type?boost::interprocess::named_condition, which is defined in?boost/interprocess/sync/named_condition.hpp. Because it is a named variable, it does not need to be stored in shared memory.?
- 例33.14使用了一個類型為boost::interprocess::named_condition的條件變量,它定義在boost/interprocess/sync/named_condition.hpp中。因為它是一個命名變量,所以不需要存儲在共享內(nèi)存中。
- 應用程序使用一個 while 循環(huán)來遞增一個類型為 int 的變量,該變量存儲在共享內(nèi)存中。雖然變量隨著循環(huán)的每次迭代而遞增,但它只會在每第二次迭代時被寫入標準輸出流--只寫奇數(shù)。每當變量遞增1時,條件變量命名為_cnd的成員函數(shù)wait()被調(diào)用。一個鎖--在例33.14中,名為鎖的變量--被傳遞給這個成員函數(shù)。這是基于RAII的習慣,即在構(gòu)造函數(shù)中取得一個mutex的所有權(quán),并在destructor中釋放它。
- 這個鎖是在while循環(huán)之前創(chuàng)建的,并且在整個程序執(zhí)行過程中擁有mutex的所有權(quán)。然而,如果將其作為參數(shù)傳遞給wait(),鎖就會自動釋放。條件變量用于等待指示等待結(jié)束的信號。同步是由成員函數(shù)wait()和notify_all()控制的。當程序調(diào)用wait()時,相應的mutex的所有權(quán)被釋放。然后,程序會一直等待,直到對同一個條件變量調(diào)用notify_all()。啟動時,例33.14似乎并沒有什么作用。在while循環(huán)內(nèi)將變量i從0增到1后,程序通過調(diào)用wait()等待信號。為了發(fā)射信號,需要啟動第二個程序?qū)嵗?/li>
- 第二個實例在進入 while 循環(huán)之前,試圖取得同一個 mutex 的所有權(quán)。由于第一個實例通過調(diào)用wait()釋放了mutex,所以成功了。因為變量已經(jīng)被遞增了一次,第二個實例執(zhí)行if表達式的else分支,并將當前值寫入標準輸出流。然后將值遞增1。現(xiàn)在第二個實例也調(diào)用wait()。然而,在這之前,它調(diào)用notify_all(),這確保了兩個實例的正確合作。第一個實例得到通知,并試圖再次獲得mutex的所有權(quán),而這個mutex仍然由第二個實例擁有。然而,由于第二個實例在調(diào)用notify_all()后立即調(diào)用wait(),它會自動釋放所有權(quán),所以第一個實例將在此時獲得所有權(quán)。兩個實例交替進行,遞增共享內(nèi)存中的變量。但是,只有一個實例將值寫入標準輸出流。當變量達到值10時,while循環(huán)就結(jié)束了。為了避免讓另一個實例永遠等待信號,循環(huán)結(jié)束后再調(diào)用一次notify_all()。在終止之前,共享內(nèi)存、mutex和條件變量被銷毀。
- 就像有兩種類型的mutexes--一種是必須存儲在共享內(nèi)存中的匿名類型,另一種是命名類型--條件變量也有兩種類型。例33.15是使用匿名條件變量重寫的上一個例子。
Example?33.15.?Using an anonymous condition with?interprocess_condition
#include <boost/interprocess/managed_shared_memory.hpp> #include <boost/interprocess/sync/interprocess_mutex.hpp> #include <boost/interprocess/sync/interprocess_condition.hpp> #include <boost/interprocess/sync/scoped_lock.hpp> #include <iostream>using namespace boost::interprocess;int main() {managed_shared_memory managed_shm{open_or_create, "shm", 1024};int *i = managed_shm.find_or_construct<int>("Integer")(0);interprocess_mutex *mtx =managed_shm.find_or_construct<interprocess_mutex>("mtx")();interprocess_condition *cnd =managed_shm.find_or_construct<interprocess_condition>("cnd")();scoped_lock<interprocess_mutex> lock{*mtx};while (*i < 10){if (*i % 2 == 0){++(*i);cnd->notify_all();cnd->wait(lock);}else{std::cout << *i << std::endl;++(*i);cnd->notify_all();cnd->wait(lock);}}cnd->notify_all();shared_memory_object::remove("shm"); }- 例33.15的工作原理和上一個完全一樣,同樣需要啟動兩次才能將int變量遞增十次。除了mutexes和條件變量,Boost.Interprocess還支持semaphores和文件鎖。Semaphores與條件變量類似,只是它們不區(qū)分兩種狀態(tài),而是基于一個計數(shù)器。文件鎖的行為類似于mutexes,只是它們用于硬盤上的文件,而不是內(nèi)存中的對象。
- 就像C++11標準庫和Boost.Thread區(qū)分不同類型的mutexes和鎖一樣,Boost.Interprocess提供了幾種mutexes和鎖。例如,mutexes可以是獨占的,也可以是非獨占的。如果多個進程需要同時讀取數(shù)據(jù),這很有幫助,因為只需要一個獨占的互斥來寫入數(shù)據(jù)。不同的鎖類可以將RAII習語應用于單個mutexes。
- 除非使用匿名同步對象,否則名稱應該是唯一的。即使mutexes和條件變量是基于不同類的對象,但對于由Boost.Interprocess封裝的操作系統(tǒng)依賴性接口來說,這不一定成立。在Windows上,mutexes和條件變量都使用相同的操作系統(tǒng)函數(shù)。如果兩個對象使用相同的名稱,每種類型的對象都有一個,那么程序在Windows上將無法正常運行。?
參考鏈接
- Synchronization
總結(jié)
以上是生活随笔為你收集整理的Synchronization 进程锁的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: IOS如何打越狱包xcode无证书打包i
- 下一篇: 对官方Mutexes的翻译