編集:私はあなたがQueue<Object> objectList
代わりに意味したと仮定していますConcurrentLinkedQueue<Object> objectList
. ConcurrentLinkedQueue<Object>
はすでにすべてのスレッド セーフを行っています。つまり、objectList.peek()
競合状態を心配することなく、必要なだけ呼び出すことができます。これは、マルチスレッド プログラムを開発している場合には便利ですが、スレッド セーフについて学ぶにはあまり適していません。
synchronized
一度にオブジェクトの 1 つのインスタンスに対して 1 つのスレッドが動作していると仮定すると、メソッドは である必要はありませんが、すべてが同じ静的クラス変数を参照するクラスの複数のインスタンスが必要な場合は、クラスをsynchronized
上書きする必要があります。次のような変数:
public static void getHeadObject() {
synchronized(safe.objectList) {
System.out.println(objectList.peek().toString());
}
}
これにより がロックobjectList
され、プログラムが同期ブロック内に入るとすぐに、他のスレッドで読み取りまたは書き込みができなくなります。他のすべてのメソッドについても同じことを行いますsynchronized
。
ノート:
ただし、単純な get 操作を 1 回しか実行していないため、競合状態では のいずれかの値または別の値を取得するため、List.peek()
を介して同期する必要はありません。競合状態の問題は、複数の複雑な読み取り/書き込み操作が実行され、それらの間で値が変化する場合です。objectList
List
たとえばPairInt
、PairInt.x
とPairInt.y
フィールドを持つクラスがあり、 という制約がx = 2y
あり、やりたかった場合
System.out.println(myIntPair.x.toString() + ", " + myIntPair.y.toString());
同時に別のスレッドが and の値を更新してx
いました。y
myIntPair.y = y + 3;
myIntPair.x = 2 * y;
myIntPair
また、読み取りスレッド間で書き込みスレッドが変更され、次のような出力が得られる場合がmyIntPair.x.toString()
あります。これは、プログラムがクラッシュする可能性があるという前提で操作している場合を意味します。myIntPair.y.toString()
(10, 8)
x == 2 * y
その場合、読み取りには を使用する必要がありますが、キュー内で変更されずに追加または削除される単純synchronized
なものなどのより単純なものの場合、ほとんどの場合、 を削除できます。実際、 、、などについては、単純な読み取りの条件を削除する必要があります。peek()
object
synchronized
string
int
bool
synchronized
ただし、書き込みは、synchronized
明示的にスレッド セーフではない操作、つまりすでに Java によって処理されている操作に対して常に行う必要があります。そして、複数のリソースを取得するか、リソースに複数行のロジックを実行するため、リソースが操作全体で同じままであることを要求するとすぐに、使用する必要があります synchronized