6

同様の質問が以前に尋ねられたことをよく知っており、操作がまったくアトミックではない可能性が高いことも認識していますが、私はまだ怠惰な好奇心から尋ねており、それをアトミックにする方法があることを願っています.

状況: 内にstruct、 という unsigned char 変数がありますBusy。(ただし、そこから移動して自立することはできます)。

この変数Busyは、2 つの並行スレッドによって変更されます。1 つはスケジューリング時にビットを設定し、もう 1 つはスケジュールされたアクションの完了時にビットをクリアします。

現在、スケジュールは次のようになっています。

while(SEC.Busy&(1 << SEC.ReqID))
    if(++SEC.ReqID == 5) SEC.ReqID = 0;
sQuery.cData[2] = SEC.ReqID;

ビットマスクのクリアは次のようになります。

SEC.Busy &= ~(1 << sQuery->cData[2]);

cData[2] は基本的に、どのスロットがネットワーク上で使用されているかに関する情報を運び、別のスレッドのコールバックを介して返されます。

質問: SEC.Busy (この問題のある状況で唯一の変数) が、mutex やクリティカル セクションなどを使用せずに同時に変更しようとする 2 つのスレッドによって引き裂かれないようにするにはどうすればよいですか?可能であれば同類の?

SEC.Busy の内容をローカル変数に割り当て、それを変更してから変数を書き戻すことも試みましたが、残念ながら、この操作もアトミックではないようです。

現在、Borland C++ Builder 6 を使用していますが、GCC ソリューションでも問題ありません。

どうもありがとうございました。

4

2 に答える 2

6

C++03 (または C99) は、アトミック性について何も述べていません。ほとんどのプラットフォームでは代入はアトミック (= 誰もが古い値か新しい値のどちらかを見る) ですが、どのプラットフォームでも同期されていないため (= 他の更新の新しい値を見た後に誰もが古い値を見る可能性がある)、とにかく役に立ちません。インクリメント、ビットの設定などの他の操作は、アトミックでさえない可能性があります。

C++11 では、原子性と同期の両方を保証するstd::atomictemplateが定義されているため、それを使用する必要があります。Boost はほとんどの C++03 コンパイラに互換性のある実装を提供し、gccは 4.2 以降組み込みサポートを提供しており、gcc 4.7 では C++11 で必要とされるより高度なサポートに置き換えられています。

Windows API には、昔から「連動操作」がありました。__syncgcc機能が導入される前に、Unix の代替として必要なアセンブリ (いくつかのライブラリが提供) が必要でした。

于 2013-06-03T09:10:38.930 に答える