2011-10-20 8 views
1
私はランダムな順序で0から4までの数字を得ることを期待、代わりに、私はいくつかの非同期の混乱私が間違って何

シンプルなマルチスレッドのミューテックスの例は間違ってい

を持って

#include <iostream> 
#include <windows.h> 
#include <process.h> 

using namespace std; 

void addQuery(void *v); 

HANDLE ghMutex; 

int main() 
{ 
    HANDLE hs[5]; 
    ghMutex = CreateMutex(NULL, FALSE, NULL);   
    for(int i=0; i<5; ++i) 
    { 
     hs[i] = (HANDLE)_beginthread(addQuery, 0, (void *)&i); 
     if (hs[i] == NULL) 
     { 
      printf("error\n"); return -1; 
     } 
    } 

    printf("WaitForMultipleObjects return: %d error: %d\n", 
     (DWORD)WaitForMultipleObjects(5, hs, TRUE, INFINITE), GetLastError()); 


    return 0; 
} 

void addQuery(void *v) 
{ 
    int t = *((int*)v); 
    WaitForSingleObject(ghMutex, INFINITE); 

    cout << t << endl; 

    ReleaseMutex(ghMutex); 
    _endthread(); 
} 
+0

["_beginthreadexで返されたスレッドハンドルを同期APIで使用することもできますが、_beginthreadでは実行できません**"](http://msdn.microsoft.com/en-us/)ライブラリ/ kdzttdcb.aspx) –

答えて

5

あなたが読んで、共有変数内部ロックを記述する必要があります。あなたはロックの外側でそれを読んでいるので、ロックは無関係です。

しかし、共有変数がロックの保護なしで書き込みを行っているループ変数であるため、それでも十分ではありません。より良い例は次のように実行します:

#include <iostream> 
#include <windows.h> 
#include <process.h> 

using namespace std; 

void addQuery(void *v); 

HANDLE ghMutex; 
int counter = 0; 

int main() 
{ 
    HANDLE hs[5]; 
    ghMutex = CreateMutex(NULL, FALSE, NULL);   
    for(int i=0; i<5; ++i) 
    { 
     hs[i] = (HANDLE)_beginthread(addQuery, 0, NULL); 
     if (hs[i] == NULL) 
     { 
      printf("error\n"); return -1; 
     } 
    } 

    printf("WaitForMultipleObjects return: %d error: %d\n", 
     (DWORD)WaitForMultipleObjects(5, hs, TRUE, INFINITE), GetLastError()); 


    return 0; 
} 

void addQuery(void *v) 
{ 
    WaitForSingleObject(ghMutex, INFINITE); 

    cout << counter << endl; 
    counter++; 

    ReleaseMutex(ghMutex); 
    _endthread(); 
} 

彼らは簡単に使用でき、より効率的であるため、あなたは、ミューテックスではなく、クリティカルセクションを使用することができます。しかし、ロックブロック内のコードだけを保護する点で同じセマンティクスを持っています。

注:Jerryは他のいくつかの問題を指摘していますが、私は高レベルの間違いや直列化に関する懸念に集中しています。

+0

ありがとう!グローバルな 'int counter'を使った例は私には明らかです。しかし、どのように私は作成されたスレッド関数にいくつかのデータを渡すことができますか? – triclosan

+0

ループカウンターへのポインタではなく、同じ方法で渡します! –

-1

​​は間違いではありません。最初のスレッドが実行されている場合 - - それはiはまだ値が0であることを保証するものではありません、その間にそれが変更された可能性があるため、

問題は、機能addQueryのパラメータの変数iのアドレスを取得することですループ内の次の値に設定します。

David Heffernanさんの回答が欲しいかもしれません。

関連する問題