c ++:为其他函数锁定互斥锁但可以并行执行的函数

时间:2015-05-23 16:58:35

标签: c++ multithreading parallel-processing mutex

我有一个关于线程安全和互斥的问题。我有两个可能无法同时执行的函数,因为这可能会导致问题:

std::mutex mutex;

void A() {
    std::lock_guard<std::mutex> lock(mutex);
    //do something (should't be done while function B is executing)
}

T B() {
    std::lock_guard<std::mutex> lock(mutex);
    //do something (should't be done while function A is executing)
    return something;
}

现在的问题是,功能A和B不应该同时执行。这就是我使用互斥锁的原因。但是,如果从多个线程同时调用函数B,则完全没问题。但是,互斥锁也可以防止这种情况(我不想这样做)。现在,有没有办法确保A和B不会同时执行,同时仍然让函数B并行执行多次?

3 个答案:

答案 0 :(得分:3)

如果选择C ++ 14,则可以使用共享互斥锁(有时称为“读写器”互斥锁)。基本上,在函数A()内部,您将获得一个唯一的(独占的“编写器”)锁,而在函数B()内,您将获得一个共享(非独占的“读者”)锁。

只要存在共享锁,就不能通过其他线程 获取互斥锁(但可以非排他地获取);只要存在独占锁,无论如何都不能通过任何其他线程获取互斥锁。

结果是您可以让多个线程同时执行函数B(),而函数A()的执行可以防止其他线程同时执行A()B()

#include <shared_mutex>

std::shared_timed_mutex mutex;

void A() {
    std::unique_lock<std::shared_timed_mutex> lock(mutex);
    //do something (should't be done while function B is executing)
}

T B() {
    std::shared_lock<std::shared_timed_mutex> lock(mutex);
    //do something (should't be done while function A is executing)
    return something;
}

请注意,即使对于B()的并发执行,也会始终存在一些同步开销,并且这是否最终会比使用普通互斥锁提供更好的性能,这在很大程度上取决于这些函数内部和外部的内容 - 在提交更复杂的解决方案之前始终进行测量。

Boost.Thread还提供了shared_mutex

的实现

答案 1 :(得分:0)

你可以选择C ++ 14 使用std::shared_timed_mutex

A会使用lockB会使用lock_shared

答案 2 :(得分:0)

这很可能充满了bug,但由于你没有C ++ 14,你可以围绕std::mutex创建一个锁定计数包装器并使用它:

// Lock-counting class
class SharedLock
{
public:
   SharedLock(std::mutex& m) : count(0), shared(m) {}

   friend class Lock;

   // RAII lock
   class Lock
   {
   public:
      Lock(SharedLock& l) : lock(l) { lock.lock(); }
      ~Lock()                       { lock.unlock(); }
   private:
      SharedLock& lock;
   };

private:

   void lock()
   {
      std::lock_guard<std::mutex> guard(internal);
      if (count == 0)
      {
         shared.lock();
      }
      ++count;
   }


   void unlock()
   {
      std::lock_guard<std::mutex> guard(internal);
      --count;
      if (count == 0)
      {
         shared.unlock();
      }
   }

   int count;
   std::mutex& shared;
   std::mutex internal;
};

std::mutex shared_mutex;

void A()
{
   std::lock_guard<std::mutex> lock(shared_mutex);
   // ...
}


void B()
{
   static SharedLock shared_lock(shared_mutex);
   SharedLock::Lock mylock(shared_lock);
   // ...
}

...当然,除非你想潜入Boost。