N実行後に「同期」したいJava/Groovyマルチスレッドプロセスがある: - スレッド実行後に共有カウンタが減少する - 目標はカウンタを一度リセットすることです他のスレッドがアクセスしていない間は0になります。N個の実行後に複数のスレッドを調整する
私はReadWriteReentrantLockで試しましたが、減量段階の競合状態があるようです。ここではおそらくのAtomicInteger値の欠落している「同期」のチェックに、私のテストコード(負のカウンタ値を持つ)は、次の奇妙な出力が得られ
public static void main(String[] args) {
AtomicInteger counter = new AtomicInteger(Decrementer.MAX_SIZE)
ReadWriteLock lock = new ReentrantReadWriteLock()
for (int i = 1; i <= 10; i++) {
Decrementer d = new Decrementer(counter, lock)
new Thread(d).start()
}
}
public class Decrementer implements Runnable {
public final static int MAX_SIZE = 5
private ReadWriteLock lock
private AtomicInteger counter
public Decrementer(AtomicInteger counter, ReadWriteLock lock) {
this.counter = counter
this.lock = lock
}
public void run() {
while (true) {
try{
lock.readLock().lock()
int current = this.counter.decrementAndGet()
System.out.println(Thread.currentThread().getName() + " at counter " + current)
Thread.sleep(762)
} finally {
lock.readLock().unlock()
}
try {
lock.writeLock().lock()
int current = this.counter.get()
if (current <= 0) {
this.counter.set(Decrementer.MAX_SIZE)
System.out.println(Thread.currentThread().getName() + " reset " + current + " to " + Decrementer.MAX_SIZE)
Thread.sleep(4217)
}
} finally {
lock.writeLock().unlock()
}
}
}
}
です。
Thread-3 at counter 2
Thread-2 at counter 4
Thread-1 at counter 3
Thread-4 at counter 1
Thread-5 at counter 0
Thread-6 at counter -1
Thread-7 at counter -2
Thread-8 at counter -3
Thread-9 at counter -4
Thread-10 at counter -5
Thread-2 reset -5 to 5
Thread-3 at counter 4
Thread-4 at counter 2
Thread-2 at counter 3
Thread-1 at counter 1
Thread-5 at counter -3
Thread-10 at counter -4
Thread-7 at counter -1
Thread-6 at counter -2
Thread-8 at counter 0
Thread-9 at counter -5
Thread-9 reset -5 to 5
私もCountDownLatchとCyclicBarrierクラスを見ましたが、私の目標は、すべてのスレッドを同期するのではなく、カウンタリセットは、原子や他のスレッドによって、他の修正を除くであることを保証するものではありません。
私のコードで見逃していた明らかな並行性の問題はありますか?
感謝を。あなたは大丈夫です:私は、読み取りロックで(カウンタに)書き込みを行っていました。 しかしあなたの解決策では、スレッドごとにWriteLockを取得しようとすると、すばやく飢餓につながります(実際に一度に1スレッドしか実行しません) 私はあなたのアドバイスをフォローアップし、書き込み部分をグループ化します(decrement + test + resetカウンタ一緒に)プロセスの読み込みロックを保持する(Sleepでシミュレート) – Wavyx
これは単なる実例であり、完全な解決策ではありません。私はまた、生産にThread.sleep(4217)を使用することを強くお勧めします! :) –