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

c++: Function that locks mutex for other function but can itself be executed in parallel

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

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并行执行多次呢?

您在 C++14 中有一个选项。
使用 std::shared_timed_mutex.

A 会使用 lock, B would use lock_shared

如果 C++14 是一个选项,您可以使用共享互斥锁(有时称为 "reader-writer" 互斥锁)。基本上,在函数 A() 内,您将获得一个唯一(独占,"writer")锁,而在函数 B() 内,您将获得一个共享(非独占,"reader")锁.

只要共享锁存在,其他线程就不能独占获取互斥量(但可以非独占地获取);只要独占锁存在,互斥量就不能被任何其他线程获取。

结果是您可以让多个线程同时执行函数 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.

的实现

这很可能充满了错误,但由于您没有 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。