2016-11-22 18 views
-1

競合状態であると判断したコードにバグがあります。断続的に発生するため、競合状態であることがわかります。これらの競合状態を防ぐためにどのように私が研究していると私は誰かが私はこれらのロックを実装する方法について、さらに詳細には触れてもらえこの競合状態を防ぐためにロックを使用する方法

 for (int i = 0; i < 10000000; i++) 
     { 
      //lock x 
      x = x + 1; 
      //unlock x 
     } 

渡って来ましたの?

+4

あなたは 'pthread'sを使用している場合は、' pthread_mutex_lock'と 'pthread_mutex_unlock' –

+1

を使用することができます最も簡単な方法は、C++ 11をお持ちの場合は、 'std :: atomic x;'です。 –

答えて

2

私はレースの条件は、典型的には、断続的に発生しないが、それは断続的に

発生するため、同様の現象を持っているバグの他の種類があり、それは競合状態である知っているので、あなたの推理は保証されません正確であること。それは、プログラムを見ずに、マルチスレッドのプログラムでは非常に起こりそうな問題であると確信しています。

誰かがこれらのロックをどのように実装する可能性があるかについて、詳細にお答えください。

C++では相互排他ロックを実装できません。これらは通常、機械命令Test-and-setを使用して実装されます。

しかし、自分でロックを実装する必要はありません。 C++ 11以降、標準ライブラリには既に実装が含まれています。さらに、より高いレベルの原子タイプ(std::atomic)を含んでいます。これは、実行を明示的にロックすることなくアトミックアクセスを提供します(アトミックタイプの実装では、ターゲットアーキテクチャに応じてロックを避けるより効率的な命令を使用することさえあります)。

標準ライブラリが古くなっている場合は、オペレーティングシステムで提供されているスレッドAPIを使用できます。ほとんどの場合、間違いなくmutexのような構造が提供されます。

4

あなたの例では、あなたのスレッドでやりたいことは、int変数の操作であることが示唆されています。それが本当の場合は、他の人が指摘しているように、std::atomicがおそらくそれを実装する最も簡単な方法でしょう。

#include <thread> 
#include <atomic> 
#include <iostream> 

std::atomic<int> x = 0; 

void increment() 
{ 
    for(int i = 0; i < 10000000; ++i) 
    { 
     ++x; 
    } 
} 

int main() 
{ 
    std::thread t1(increment); 
    std::thread t2(increment); 

    t1.join(); 
    t2.join(); 

    std::cout << x; 
} 

しかし、同時に複数のスレッドで実行されることから、より複雑な操作を保護するために、あなたはstd::lock_guardを使用する必要があります。 RAII(リソース獲得は初期化です)原則を使用して、その存続期間中にmutexをロックします。

#include <thread> 
#include <mutex> 
#include <iostream> 

int x = 0; 
std::mutex mtx; 

void increment() 
{ 
    for (int i = 0; i < 10000000; i++) 
    { 
     std::lock_guard<std::mutex> lock(mtx); //lock mtx 
     ++x; 

     // mtx is automatically released when lock 
     // goes out of scope -> RAII 
    } 
} 

int main() 
{ 
    std::thread t1(increment); 
    std::thread t2(increment); 

    t1.join(); 
    t2.join(); 

    std::cout << x; 
} 

ここにあなたのコメントに基づいてEDIT

は別の例である:

#include <thread> 
#include <mutex> 
#include <iostream> 

class Foo 
{ 
public: 
    void increment() 
    { 
     for (int i = 0; i < 10000000; ++i) 
     { 
      std::lock_guard<std::mutex> lock(mtx); //lock mtx 
      ++x; 

      // mtx is automatically released when lock 
      // goes out of scope -> RAII 
     } 
    } 

    void decrement() 
    { 
     for (int i = 0; i < 10000000; ++i) 
     { 
      std::lock_guard<std::mutex> lock(mtx); //lock mtx 
      --x; 

      // mtx is automatically released when lock 
      // goes out of scope -> RAII 
     } 
    } 

    static int x; 
    static std::mutex mtx; 
}; 

int Foo::x = 0; 
std::mutex Foo::mtx; 

int main() 
{ 
    std::thread t1(&Foo::increment, Foo()); 
    std::thread t2(&Foo::decrement, Foo()); 

    t1.join(); 
    t2.join(); 

    std::cout << Foo::x; 
} 
+0

変数がオブジェクトメンバ関数内にある場合でも、このコードを実装できますか? – MagnusHimmler

+0

私はあなたを正しく理解しているかわかりません。ちょっとした例であなたの質問を編集できますか?しかし、変数が一部のメンバ関数のローカル変数である場合、この変数に関する問題が競合条件であるとはほとんど疑いがありません。 – sigy

+0

私は同じオブジェクト内の2つの異なる関数によってアクセスされる静的変数を持っています。しかし時には2番目の関数がこの変数をスキップすることもあります – MagnusHimmler

関連する問題