1


0

この問題は、ワーカースレッドでシングルトンオブジェクトの取得メソッドを使用することについてです。 これが最初の擬似コードです。

// Singleton class which contains data
クラスMyData {static MyData * sMyData;

int mData1 [1024]。 int mData2 [1024]; int mData3 [1024]。

MyData * getInstance(){// sMyDataは最初のうちに作成されます。 sMyDataを返します。 }

void getValues(int idx、int

int * getData1(){return

クラスMyThread {void workerMethod(){MyData * md = MyData :: getInstance();}

int d1、d2、d3。 md-> getValue(12、d 1、d 2、d 3);

int * data1 = md-> getData1(); d1 =データ1 [34]。 }}
ご覧のとおり、私はいくつかのgetterメソッド(すべて読み取り専用)、MyData

getInstance()、MyData :: getValue()、およびMyData :: getData1()を持っています。 最初の質問は、これらのメソッドがどの程度スレッドセーフであるかということです。

それらはしばしばメソッドと呼ばれるので、ミューテックスでそれらのメソッドを保護することは私が避けようとしているものです。

2つ目の質問は、マルチスレッドアプリケーション、特にワーカーメソッドで中央ソースからデータを読み取るための推奨される方法は何ですか?です。

ありがとうございます。

ポール

5 Answer


5


他のスレッドが自分のシングルトンオブジェクトのデータに書き込もうとしないのであれば、それらを保護する必要はありません。定義上、ライターが存在しない場合の複数のリーダーはスレッドセーフです。 これは、プログラムの初期化コードがシングルトンを設定する一般的なパターンです。シングルトンは、ワーカースレッドによってのみ読み取られます。

ただし、他の人が読み取り中に_any _ thread _ever_がこのデータに書き込む場合は、何らかの方法で保護する必要があります。 たくさんの読者がいて、たまにしか書いていない人がいるのなら、作家がいなくても複数の読者に許可される、ある種の「読み書き」ロックを検討する価値があります。


2


これがスレッドセーフかどうかを判断することは不可能です。 データがオブジェクトの作成中に初期化され、変更されることがない場合は、これは正しく実行されます。 あなたが他の方法で基礎となるデータを変更しているならば、読者は作家に対してある種の同期を実行しなければならないでしょう、それを回避する方法はありません。

実行している内容によっては、アトミック更新同期コマンドやリーダー/ライターロックの使用など、ミューテックスよりも軽量なものを使用できる場合がありますが、何をしているのかを知らなくてもわかりません。


1


あなたの方法は問題ありませんが、2つの大きな問題があります。

まず、MyData

getInstance()は静的である必要があり、インスタンスを作成しません。 ミューテックスの使用を最小限に抑えるためには、http://en.wikipedia.org/wiki/Double_checked_locking_pattern [double checked lock]をチェックしてください。

第二に、スレッドの安全性は、MyDataクラスではなくgetterメソッドの呼び出し元次第です。 それがあなたが探しているものであれば、それから素晴らしいです。 そうでない場合は、MyClassで何らかのアクセス制御を考え出す必要があります。 また、含まれているデータ型は基本型(int)にすぎないので、コードが本番になるまで同期の問題が発生することは決してありません。


1


最初に戻ってsingeltonのより良いバージョンを入手するためにこの質問を読んでください: https://stackoverflow.com/questions/270947/can-any-one-provide-me-a-sample-of-singleton-in-c[Can誰かがシングルトンのサンプルをcで提供してくれますか。

また、注意してください。絶対化されたグローバル変数としてシングルトンを使用しないでください。 悪いデザインに複雑さを加えるだけです。 グローバル変数を使うだけです。

あなたがシングルトンから読んでいるだけである限り、使用されているときそれはスレッドセーフです。

スレッドセーフではない(言語によって保証されていない)唯一のポイントは作成中です。 技術的には、インスタンスを作成する部分の周囲にロックを追加して、誰かがそれを使用できるようになる前に、シングルトンが完全に作成されたことを保証する必要があります。

注:ロック戦略を最適化するためにダブルチェックロックを使用しても気にしないでください。 Cでは正しく動作させることはできません。 DDJの記事を読んでください。

シングルトンがシングルスレッド環境内で(おそらく最初の呼び出しでもgetInstance()も)インスタンス化されることを保証できる場合(スレッドが作成される前)、インスタンス化中のロックの必要性を省くことができます。

他のスレッドがシングルトンに書き込めるようにコードを変更する場合は、ロックと一貫性について考える必要があります。 書き込みがアトミックではない場合にのみロックが必要です。 あなたの書き込みがただ1つの整数を更新しているなら、それはすでにアトミックであり、変更は必要ありません。 コードがアトミックではない場合

  • メソッド内で複数の整数を書く

  • 読み取りを実行してから書き込みを実行する

その後、すべての書き込みが完了するまでオブジェクトをロックする必要があります。その結果、他のメソッドがオブジェクトを更新している間は、オブジェクトからの読み取りを停止するために読み取りアクセス権を持つメソッドもロックします。

その結果、メンバー変数がメンバーメソッドによってのみアクセスされるべきであるもう1つの理由です。


0


スレッドを安全にするために、クラス全体を見る必要があります。 書かれたようにあなたのクラスはスレッドセーフではないでしょう。 getValuesメソッドは問題ありませんが、getData1メソッドには問題があります。

あなたはそれらが(読み取り専用)ゲッターメソッドであると言います。 ただし、どちらもconstメソッドとして宣言されていません。 getData1は、constでないポインタを返すため、constメソッドとしては無効です。 さらに、プライベートクラスのデータへのポインタを返すことは、実装を公開しているため、不適切です。

スレッド化が始まる前に初期化時に本質的に静的なデータセットを保持するシングルトンクラスであれば、すべてのアクセサはconstメソッドであるべきです。 getInstanceはクラスへのconstポインタも返すべきです(そして別の答えで述べたように静的メソッドであるべきです)。