如何使用boost可升级互斥锁的示例

时间:2010-10-09 09:17:25

标签: c++ boost-thread boost-interprocess

我有一个多线程服务器应用程序需要对某些共享内存进行互斥锁定。

共享内存基本上是sTL地图等。

我刚从地图上读书的很多时候。 但是,我还需要偶尔添加它。

e.g。     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?
    }

2 个答案:

答案 0 :(得分: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,因此有人可能会删除此节点,并且当您到达写入部分时它不再有效。错误,抱歉。

编辑:我认为boost 中的explanation清除。无论如何,让我们试着改写一下:

有三种主要类型的互斥锁概念(我不计算TimedLockable,因为它与您的问题无关):

  • 可锁定 - 只是一个简单的独占所有权互斥锁。如果有人锁定()s没有人可以再次锁定()它,直到所有者解锁()它。 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进行升级。

答案 1 :(得分:5)

如果您只使用一个流程,则不需要boost-interprocess。正如库名所暗示的那样,它用于进程间通信(IPC)。您最有可能想要使用boost-thread mutex 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来解释这一点。