2

多个线程 ( std::async) 通过 a 共享以下类的实例shared_ptr,是否有可能在这部分代码中出现分段错误?如果我的理解std::mutex是正确的,mutex.lock()则会导致所有其他线程试图调用mutex.lock()阻塞直到mutex.unlock()被调用,因此对向量的访问应该完全按顺序进行。我在这里错过了什么吗?如果没有,是否有更好的方法来设计这样的类(也许使用 a std::atomic_flag)?

#include <mutex>
#include <vector>
class Foo
{
   private:
      std::mutex mutex;
      std::vector<int> values;
   public:
      Foo();
      void add(const int);
      int get();
};
Foo::Foo() : mutex(), values() {}
void Foo::add(const int value)
{
   mutex.lock();
   values.push_back(value);
   mutex.unlock();
}
int Foo::get()
{
   mutex.lock();
   int value;
   if ( values.size() > 0 )
   {
      value = values.back();
      values.pop_back();
   }
   else
   {
      value = 0;
   }
   mutex.unlock();
   return value;
}

免责声明:默认值 0 inget()是因为它在代码的其余部分具有特殊含义。

更新:上面的代码与我使用的完全一样,当然除了拼写错误 push_Back。

4

2 回答 2

2

除了不使用 RAII 来获取锁并使用size() > 0而不是!empty(),代码看起来不错。这正是互斥锁的使用方式,这是您需要互斥锁的方式和位置的典型示例。

正如 Andy Prowl 所指出的,实例不能被复制构造或复制分配。

于 2013-02-12T13:53:44.920 回答
1

这是“改进”版本:

#include <mutex>
#include <vector>
class Foo {
   private:
      std::mutex mutex;
      typedef std::lock_guard<std::mutex> lock;
      std::vector<int> values;
   public:
      Foo();
      void add(int);
      int get();
};
Foo::Foo() : mutex(), values() {}
void Foo::add(int value) {
   lock _(mutex);
   values.push_back(value);
}
int Foo::get() {
   lock _(mutex);
   int value = 0;
   if ( !values.empty() )
   {
      value = values.back();
      values.pop_back();
   }
   return value;
}

与 RAII 获取mutex等。

于 2013-02-12T15:08:20.863 回答