1

スレッドセーフではないため、スレッドセーフにする非常に単純なカプセル化std::vectorを構築しようとしていました。

これは非常にうまく機能しますが、小さな問題が 1 つあります。クラスのインスタンスが破棄され、別のスレッドがまだそのインスタンスからデータを読み取ろうとしている場合、スレッドは永久にハングし続けます。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();
}

編集定義を変更する必要があります。前に述べたように、コンテナは明らかにスレッドセーフではありません。命名法が誤解を招くものであっても、そうすることは想定されていません。確かに、まったくスレッドセーフではないことを行うことができます! ただし、コンテナーに書き込むスレッドは 1 つだけで、コンテナーから読み取るスレッドは 2 つまたは 3 つです。プロセスを停止しようとするまではうまくいきます。モニターの方が良かったと言わざるを得ません。しかし、時間がなくなり、それまでこれを変更することはできません。

どんなアイデアでも大歓迎です!ありがとうございます。

4

1 に答える 1

1

編集:より完全な例に更新されました。

他の人は、「スレッドセーフ」の欠陥を指摘しています。私はあなたの質問に答えようとします。

やろうとしていることを実行する唯一の適切な方法は、ベクター自体を破壊しようとする前に、すべてのスレッドがシャットダウンされていることを確認することです。

私が使用した一般的な方法は、単純に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;
};

複数のリーダーとライターを使用できる、より完全なスレッド セーフなデータ構造を探している場合は、私が以前にブースト スレッドを使用して作成したキューを自由にチェックしてください。

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

于 2012-01-15T04:17:44.747 に答える