9

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

共享内存基本上是 sTL 映射等。

很多时候我只是在看地图。但是,我也需要偶尔添加它。

例如 typedef std::map MessageMap; 消息映射消息映射;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.
}

编辑:我可能会混淆不同的锁类型。

共享/升级和独占之间有什么区别。即我不明白解释。听起来如果您只想允许大量读者,那么您想要获得的只是共享访问权限。而要写入您的共享内存,您只需要升级访问权限。还是你需要独家?boost 中的解释并不明确。

是否获得了升级访问权限,因为您可能会写。但是共享意味着你肯定不会写是什么意思?

编辑:让我更清楚地解释我想要做什么。我对答案还不满意。

这里又是一个例子,但还有一个我正在使用的代码的例子。只是一个插图,而不是实际的代码。

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?
    }
4

2 回答 2

15

你说你的应用程序是多线程的,所以你应该使用 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中的解释清楚。无论如何,让我们试着改写给你:

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

  • 可锁定——只是一个简单的独占所有权互斥锁。如果有人锁定()它,没有人可以再次锁定()它,直到所有者解锁()它。boost::thread::mutex 实现了这个概念。要以 RAII 样式锁定此概念,请使用 lock_guard 或 unique_lock 以获得更复杂的界面。
  • SharedLockable — 是具有额外“共享”所有权的 Lockable。您可以使用 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 进行升级。
于 2010-10-09T09:49:02.033 回答
5

boost-interprocess如果你只使用一个进程,你不想要。正如库名称所暗示的那样,它用于进程间通信 (IPC)。您很可能希望使用boost-thread 互斥锁和锁定概念

#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 邮件列表上也有一篇文章对此进行了解释。

于 2010-10-09T18:08:55.720 回答