1

私は最近使用してJava Threadsいて、コードのブロックを「シングル」と呼ばれる1つのスレッドのみで実行されるように制限できるメソッドを実装しようとしています。

私がすでに実装した素朴な解決策は次のとおりです。

if(readFlag())
{
  synchronized(this)
  {
  flag = false;  
  // do some work
  }
} 

どこ :

public Boolean synchronized readFlag() {return flag;}

この素朴な解決策は、1 つの「単一」ブロックに対してのみ正常に機能しますが、複数の「単一」コード ブロックを使用しようとすると問題が発生します。異なるスレッドが異なる「単一の」コードブロックを同時に入力する可能性があるため、同じフラグを使用することはできません。

別の解決策として、"単一" ごとに 1 つのフラグ変数の配列を使用することもできますが、この解決策では、ループ内で "単一" コード ブロックを実行するときに問題が発生する (またはバリアを使用する必要がある) だけでなく、柔軟性があまり高くありません。

私の質問は:

このソリューションを改善して、さまざまな「単一」コード ブロックの実行を許可し、同じ単一コード ブロックを複数回実行できるようにするにはどうすればよいでしょうか (たとえば、ループ内の単一コード ブロック)。

4

2 に答える 2

4

同期するオブジェクトを変更できます。必要でない限り、 で同期する必要はありませんthis。同期する必要があるが両方を同時に実行できる (それぞれ 1 つのスレッドのみ) 2 つのブロックがある場合は、次のようなことができます。

private final Object lock1 = new Object();
private final Object lock2 = new Object();
...
synchronized(lock1) { // do stuff. the code in lock2 can be executed while another thread is executing this }
synchronized(lock2) { // do stuff. the code in lock1 can be executed while another thread is executing this }

また、より洗練されたロック (複数のリーダーと 1 つのライターのみを許可する) については、 ReentrantReadWriteLockを参照してください。

于 2012-10-30T21:51:29.177 に答える
3

過去数日間、同様の問題に遭遇しました。私の場合、ConcurrentMap でクリーンアップ タスクを実行する必要があり、10 分ごとに 1 つのスレッドだけがタスクを実行する必要があります。ConcurrentMap イテレーターは ConcurrentModificationException をスローしないことを保証しているため、同期する必要はありませんでした。1 つのスレッドだけがクリーンアップ タスクを実行するようにするために、AtomicBoolean を使用しました。

AtomicBoolean flag = new AtomicBoolean(false);
...

boolean proceed = flag.compareAndSet(false , true);
if(proceed){
   doStuff();
   flag.set(false);
}

したがって、これによりブール値フラグでの同期が回避されます。同期するコードのさまざまな部分については、ジェフに同意します。さまざまなオブジェクトで同期できます。

于 2012-10-30T22:20:21.200 に答える