2017-02-09 10 views
1

私は小さな問題があり、誰かが助けてくれるのだろうかと思っています。私は可能な限り簡単な方法で問題を実証しようとしました。私は複数のスレッドへの参照によってオブジェクトを渡そうとしています。すべてのスレッドは、オブジェクト "Example"に属するメンバ関数である "doSomething"を呼び出します。 "doSomething"関数は、カウンタをインクリメントする必要があります。私のgccのバージョンは4.4.7参照とマルチスレッドによるオブジェクトの受け渡し

質問です:私はスレッド関数への参照によって、オブジェクトを通過したものの、変数「カウンタ」の値がインクリメントされないされている理由

コード:

#include <iostream> 
#include <thread> 

class Exmaple { 
    private: 
     int counter; 

    public: 
      Exmaple() { 
      counter = 0; 
     }  

     void doSomthing(){ 
      counter++; 
     } 

     void print() { 
      std::cout << "value from A: " << counter << std::endl; 
     } 

}; 

// notice that the object is passed by reference 
void thread_task(Exmaple& o) { 
    o.doSomthing(); 
    o.print(); 
}  

int main() 
{ 
    Exmaple b; 
    while (true) { 
     std::thread t1(thread_task, b); 
     t1.join(); 
    }  
    return 0; 
} 

出力:あなたがここに知っておく必要があり

value from A: 1 
value from A: 1 
value from A: 1 
value from A: 1 
value from A: 1 
value from A: 1 
value from A: 1 
value from A: 1 
value from A: 1 
+1

あなたはあなたが 'atomic_int'または同期させるためのいくつかの他の手段を必要とする – RbMm

答えて

5
while (true) { 
    std::thread t1(thread_task, b); 
    t1.join(); 
} 

2つのこと:

  • std::refを使用して参照を渡します。
  • 無限ループは未定義C++での動作。以下

実施例:

#include <iostream> 
#include <thread> 

class Exmaple { 
    private: 
     int counter; 

    public: 
      Exmaple() { 
      counter = 0; 
     }  

     void doSomthing(){ 
      counter++; 
     } 

     void print() { 
      std::cout << "value from A: " << counter << std::endl; 
     } 

}; 

// notice that the object is passed by reference 
void thread_task(Exmaple& o) { 
    o.doSomthing(); 
    o.print(); 
}  

int main() 
{ 
    Exmaple b; 
    for(int i =0; i < 10; i++) { 
     std::thread t1(thread_task, std::ref(b)); 
     t1.join(); 
    }  
    return 0; 
} 

出力:

value from A: 1 
value from A: 2 
value from A: 3 
value from A: 4 
value from A: 5 
value from A: 6 
value from A: 7 
value from A: 8 
value from A: 9 
value from A: 10 

はそれLive参照してください。

ものの行く、さらにあなたはまた、データ競合

+0

連動増分を必要とします。 – juanchopanza

+0

私は不思議です、私は無限ループを知りませんでした。どこでC++での定義されていない動作がありましたか、そのようなループを書く正しい方法は何でしょうか? – ShadowMitia

+0

ああ、あなたはそれを持っています。ありがとう!! –

4

検討すべきである私は、マルチスレッドに非常に慣れていないんだけど、あなたは参照することによりスレッドに値でbを渡すと、していません。値は常にthe documentationによる1

あるのでbの値は、その後、thread_taskを参照して渡され、あなたはとても参照によってオブジェクトを渡すようなあなたのスレッドを記述する必要があります。

std::thread t1(thread_task, std::ref(b)); 
+0

あなたの説明をいただきありがとうございます。 –

0

。なお、 std::thread t1(thread_task, b)の場合のコンストラクタに値でbを渡します(ここでコンストラクタを呼び出すと、thread_taskではなく)。解決策はstd::ref -objectでbを包む、またはポインタを渡すようにコードを変更するのいずれかである可能性があり:

void thread_task(Exmaple* o) { 
    o->doSomthing(); 
    o->print(); 
} 

int main() 
{ 
    Exmaple b; 
    while (true) { 
     std::thread t1(thread_task, &b); 
     t1.join(); 
    } 
    return 0; 
} 
関連する問題