c++ - 从析构函数中释放 boost::mutex

标签 c++ destructor boost-thread boost-mutex

由于 std::vector 不是线程安全的,我试图围绕它构建一个非常简单的封装,使其成为线程安全的。

这工作得很好,但有一个小问题。 当类的实例正在被破坏并且另一个线程仍在尝试从中读取数据时,该线程将永远卡在 boost::mutex::scoped_lock lock(m_mutex);

我该如何解决这个问题?最好的办法是只解锁互斥量,以便卡在其中的线程可以继续执行。我没有定义析构函数,因为直到现在,它还不是必需的。

这是我的代码。请注意,这里显示的方法比这里显示的要多,它已经过简化。

template<class T>
class SafeVector 
{
    public:
    SafeVector();
    SafeVector(const SafeVector<T>& other);

    unsigned int size() const;
    bool empty() const;

    void clear();
    T& operator[] (const unsigned int& n);

    T& front();
    T& back();

    void push_back(const T& val);
    T pop_back();

    void erase(int i);

    typename std::vector<T>::const_iterator begin() const;
    typename std::vector<T>::const_iterator end() const;

    const SafeVector<T>& operator= (const SafeVector<T>& other);

    protected:
    mutable boost::mutex m_mutex;
    std::vector<T>  m_vector;

};

template<class T>
SafeVector<T>::SafeVector()
{

}

template<class T>
SafeVector<T>::SafeVector(const SafeVector<T>& other)
{
    this->m_vector = other.m_vector;
}

template<class T>
unsigned int SafeVector<T>::size() const
{
    boost::mutex::scoped_lock lock(m_mutex);
    return this->m_vector.size();
}

template<class T>
bool SafeVector<T>::empty() const
{
    boost::mutex::scoped_lock lock(m_mutex);
    return this->m_vector.empty();
}

template<class T>
void SafeVector<T>::clear()
{
    boost::mutex::scoped_lock lock(m_mutex);
    return this->m_vector.clear();
}

template<class T>
T& SafeVector<T>::operator[] (const unsigned int& n)
{
    boost::mutex::scoped_lock lock(m_mutex);
    return (this->m_vector)[n];
}

template<class T>
T& SafeVector<T>::front()
{
    boost::mutex::scoped_lock lock(m_mutex);
    return this->m_vector.front();
}

template<class T>
T& SafeVector<T>::back()
{
    boost::mutex::scoped_lock lock(m_mutex);
    return this->m_vector.back();
}

template<class T>
void SafeVector<T>::push_back(const T& val)
{
    boost::mutex::scoped_lock lock(m_mutex);
    return this->m_vector.push_back(val);
}

template<class T>
T SafeVector<T>::pop_back()
{
    boost::mutex::scoped_lock lock(m_mutex);
    T back = m_vector.back();
    m_vector.pop_back();
    return back;
}

template<class T>
void SafeVector<T>::erase(int i)
{
    boost::mutex::scoped_lock lock(m_mutex);
    this->m_vector.erase(m_vector.begin() + i);
}

template<class T>
typename std::vector<T>::const_iterator SafeVector<T>::begin() const
{
    return m_vector.begin();
}

template<class T>
typename std::vector<T>::const_iterator SafeVector<T>::end() const
{
    return m_vector.end();
}

编辑 我必须更改我的定义。如前所述,容器显然不是线程安全的。它不应该这样做——即使术语具有误导性。当然,您可以用它做一些根本不是线程安全的事情!但是只有一个线程写入容器,2 或 3 个线程从中读取。在我尝试停止该过程之前,它运行良好。我不得不说显示器会更好。但时间不多了,我不能在那之前改变这一点。

任何想法表示赞赏!谢谢和问候。

最佳答案

编辑:更新为更完整的示例。

其他人指出了您的“线程安全”的缺陷;我会尝试回答您的问题。

要完成您计划要做的事情,唯一正确的方法是确保在尝试销毁 vector 本身之前关闭所有线程。

我用过的一个常用方法是简单地使用 RAII定义构造和破坏的顺序。

void doSomethingWithVector(SafeVector &t_vec)
{
  while (!boost::this_thread::interruption_requested())
  {
    //operate on t_vec
  }
}

class MyClassThatUsesThreadsAndStuff
{
  public:
    MyClassThatUsesThreadsAndStuff()
      : m_thread1(&doSomethingWithVector, boost::ref(m_vector)),
        m_thread2(&doSomethingWithVector, boost::ref(m_vector))
    {
      // RAII guarantees that the vector is created before the threads
    }

    ~MyClassThatUsesThreadsAndStuff()
    {
      m_thread1.interrupt();
      m_thread2.interrupt();
      m_thread1.join();
      m_thread2.join();
      // RAII guarantees that vector is freed after the threads are freed
    }

  private:
    SafeVector m_vector;
    boost::thread m_thread1;
    boost::thread m_thread2;
};

如果您正在寻找允许多个读取器和写入器的更完整的线程安全数据结构,请随时查看我不久前使用 boost 线程编写的队列。

http://code.google.com/p/crategameengine/source/browse/trunk/include/mvc/queue.hpp

关于c++ - 从析构函数中释放 boost::mutex,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8862568/

相关文章:

C++ 私有(private)访问其他类的成员

c++ - 如何实现动态线程Boost::Barrier?

c++ - 以 3 函数的中位数进行的比较次数?

c++ - 为什么不能在声明范围之外访问用new声明的变量?

c++ - 异常规范如何影响虚拟析构函数覆盖?

c++ - 为什么 C++ 析构函数会发生这种情况?

c++ - boost::asio 与 boost::unique_future

c++ - 我如何使用 §8.3.1 和 §8.3.4 推断像 '[]' 这样的后缀声明符运算符比像 '*' 这样的前缀运算符绑定(bind)得更紧密?

c++ - 正确使用模板函数

c++ - 限制对 C++ 构造函数和析构函数的访问