2010-10-09 40 views
7

我有一個多線程的服務器應用程序,它需要對某些共享內存進行互斥鎖。如何使用boost升級互斥體的示例

共享內存基本上都是STL地圖等

很多時候我只是從地圖上讀出。 但是,我也需要偶爾加入它。

例如 typedef std :: map MessageMap; MessageMap msgmap; boost:shared_mutex access_;

void ProcessMessage(Message* message) 
{ 
    // Access message... read some stuff from it message->... 

    UUID id = message->GetSessionID(); 

    // Need to obtain a lock here. (shared lock? multiple readers) 
    // How is that done? 
    boost::interprocess::scoped_lock(access_); 

    // Do some readonly stuff with msgmap 
    MessageMap::iterator it = msgmap.find(); 
    // 

    // Do some stuff... 

    // Ok, after all that I decide that I need to add an entry to the map. 
    // how do I upgrade the shared lock that I currently have? 
    boost::interprocess::upgradable_lock 


    // And then later forcibly release the upgrade lock or upgrade and shared lock if I'm not looking 
    // at the map anymore. 
    // I like the idea of using scoped lock in case an exception is thrown, I am sure that 
    // all locks are released. 
} 

編輯: 我可能會混淆不同的鎖類型。

共享/升級和獨家之間有什麼區別。 即我不明白解釋。 聽起來好像你只是想允許很多讀者,共享訪問就是你想要的。要寫入共享內存,您只需要升級訪問權限。或者你需要獨家?提振的解釋是非常明確的。

是否因爲可能寫入而獲得升級訪問權限。但共享意味着你肯定不會寫這是什麼意思?

編輯:讓我解釋一下我想要做的更清晰一點。我還不滿意答案。

這裏是一遍又一遍的例子,但也有一些我正在使用的代碼的例子。 只是一個說明,而不是實際的代碼。

typedef boost::shared_mutex Mutex; 
typedef boost::shared_lock<Mutex> ReadLock; 
typedef boost::unique_lock<Mutex> WriteLock; 
Mutex mutex; 
typedef map<int, int> MapType; // Your map type may vary, just change the typedef 
MapType mymap; 

void threadoolthread() // There could be 10 of these. 
{ 
    // Add elements to map here 
    int k = 4; // assume we're searching for keys equal to 4 
    int v = 0; // assume we want the value 0 associated with the key of 4 

    ReadLock read(mutex); // Is this correct? 
    MapType::iterator lb = mymap.lower_bound(k); 
    if(lb != mymap.end() && !(mymap.key_comp()(k, lb->first))) 
    { 
     // key already exists 
    } 
    else 
    { 
     // Acquire an upgrade lock yes? How do I upgrade the shared lock that I already  have? 
     // I think then sounds like I need to upgrade the upgrade lock to exclusive is that correct as well? 

     // Assuming I've got the exclusive lock, no other thread in the thread pool will be able to insert. 
     // the key does not exist in the map 
     // add it to the map 
     { 
      WriteLock write(mutex, boost::adopt_lock_t()); // Is this also correct? 
      mymap.insert(lb, MapType::value_type(k, v)); // Use lb as a hint to insert, 
                 // so it can avoid another lookup 
     } 
     // I'm now free to do other things here yes? what kind of lock do I have here, if any? does the readlock still exist? 
    } 

回答

11

你說你的應用程序是多線程的,所以你應該使用boost :: thread而不是boost :: interprocess。

從文檔(未測試),你應該這樣來做:

typedef boost::thread::shared_mutex shared_mutex; 
boost::thread::upgrade_lock<shared_mutex> readLock(access_); 

// Read access... 

boost::thread::upgrade_to_unique_lock<shared_mutex> writeLock(readLock); 

// Write access.. 

另外請注意,您獲得 it當你鎖定的讀訪問,所以有人可能會刪除此節點,它不再有效當你到達寫入部分。 錯誤,對不起。

編輯:我覺得explanation在提升明確。讓我們試一下改寫到你啦:

主要有三種類型的互斥概念(因爲它是不相關的問題,我不指望TimedLockable):

  • 上鎖 —只是一個簡單的,獨佔所有權互斥體。如果某人鎖定(),則沒有人可以再次鎖定(),直到擁有者解鎖()。 boost :: thread :: mutex實現了這個概念。要以RAII風格鎖定此概念,請使用lock_guard或unique_lock以獲得更復雜的界面。
  • SharedLockable —是一個可鎖定的附加「共享」所有權。您可以通過lock()或lock_shared()獲得共享所有權。如果您鎖定共享部分不能將您的所有權升級爲獨佔部分。您需要再次unlock_shared()和lock(),這意味着其他人可能會修改unlock_shared()和lock()之間的受保護資源。當你事先知道你將要做什麼樣的資源訪問時,這很有用。 shared_mutex實現了這個概念。使用lock_guard或unique_lock獲取獨佔所有權和shared_lock以獲取共享所有權。
  • UpgradeLockable —是SharedLockable,它允許您從共享所有權升級到獨佔所有權而無需解鎖。 shared_mutex也實現了這個概念。您可以使用上述鎖來獲得排他或共享所有權。要獲得可升級的共享所有權,請使用upgrade_lock並使用upgrade_to_unique_lock進行升級。
+0

對不起,我想也許我想使用boost :: upgrade_lock和boost :: upgrade_to_unique_lock。也許你可以解釋他們之間的差異。看到我編輯的問題。 – Matt 2010-10-09 09:55:31

+0

@Matt H:見編輯答案。 – ybungalobill 2010-10-09 18:49:26

+0

有了UpgradeLockable,那裏只能有一個線程處於該狀態,但有幾個可以在SharedLockable中是正確的?所以爲了使升級鎖成爲唯一鎖,所有共享鎖都需要解鎖正確? – Matt 2010-10-10 03:23:38

5

如果您只使用單個進程,則不需要​​。正如庫名所暗示的那樣,它用於進程間通信(IPC)。您最有可能要使用boost-threadmutex and locking concepts

#include <boost/thread/locks.hpp> 
#include <boost/thread/shared_mutex.hpp> 

int 
main() 
{ 
    typedef boost::shared_mutex Mutex; 
    typedef boost::shared_lock<Mutex> ReadLock; 
    typedef boost::unique_lock<Mutex> WriteLock; 
    Mutex mutex; 

    { 
     // acquire read lock 
     ReadLock read(mutex); 

     // do something to read resource 
    } 

    { 
     // acquire write lock 
     WriteLock write(mutex, boost::adopt_lock_t()); 

     // do something to write resource 
    } 
} 

在boost郵件列表中有一個post解釋這一點。

+1

編輯:謝謝薩姆。你能看看我上面的例子,我在問題底部編輯過。那會是正確的用法嗎? – Matt 2010-10-09 23:51:30

+1

@Matt,在你的情況下,因爲在進入'threadoolthread'時無條件獲取讀鎖,我想你想使用'boost :: upgrade_to_unique_lock' ybungalobill [描述](http://stackoverflow.com/questions/3896717 /例如-的,如何使用的升壓 - 升級 - 互斥/ 3896816#3896816)。雖然,我從來沒有使用'boost :: adopt_lock_t()',所以我不熟悉這種行爲,也許它有效。 – 2010-10-10 00:17:04

+0

不會在線程池函數的開頭使用upgrade_to_unique_lock意味着線程池中只有一個線程可以一次運行? – Matt 2010-10-10 00:47:26