首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >N次执行后协调多线程

N次执行后协调多线程
EN

Stack Overflow用户
提问于 2016-11-05 16:38:44
回答 2查看 219关注 0票数 0

我有一个Java/Groovy多线程进程,我想在N个执行之后“同步”:-在每个线程执行之后,一个共享计数器会减少--目标是当计数器达到0时重置,而没有其他线程正在访问它。

我尝试了一个ReadWriteReentrantLock,但它看起来我有一个减少阶段的竞赛条件。这是我的测试代码

代码语言:javascript
复制
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()
            }
        }
    }
}

它提供了以下奇怪的输出(带有负的计数器值),可能是由于缺少了AtomicInteger值的“同步”检查。

代码语言:javascript
复制
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

我还看到了CountDownLatchCyclicBarrier类,但我的目标不是同步所有线程,而是确保计数器重置是原子的,并排除其他线程的其他修改。

您看到我的代码中遗漏了什么明显的并发问题吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-11-05 17:03:32

你的锁反之亦然。你正在获取读锁,然后做“写”。这应该是可行的:

代码语言:javascript
复制
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();
    }
}

static 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.writeLock().lock();
                int current = this.counter.decrementAndGet();
                System.out.println(Thread.currentThread().getName() + " at counter " + current);
                if (current <= 0) {
                    this.counter.set(Decrementer.MAX_SIZE);
                    System.out.println(Thread.currentThread().getName() + " reset " + current + " to " + Decrementer.MAX_SIZE);
                    Thread.sleep(4217);
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock.writeLock().unlock();
            }
        }
    }
}
票数 1
EN

Stack Overflow用户

发布于 2016-11-15 12:53:13

基于写锁获取注释,下面是工作解决方案:

代码语言:javascript
复制
public class Decrementer implements Runnable {

public final static int MAX_SIZE = 20;
private ReadWriteLock lock;
private AtomicInteger counter;

public Decrementer(AtomicInteger counter, ReadWriteLock lock) {
    this.counter = counter;
    this.lock = lock;
}

public void run() {

    while (true) {
        int current
        try {
            lock.writeLock().lock();
            if (this.counter.compareAndSet(0, Decrementer.MAX_SIZE)) {
                current = 0;
                flushWork(current);
            } else {
                current = counter.decrementAndGet();
                System.out.println(Thread.currentThread().getName() + " decrement  " + current);
            }
        } finally {
            lock.writeLock().unlock();
        }

        try {
            lock.readLock().lock();
            doWork(current);
        } finally {
            lock.readLock().unlock();
        }
    }
}

private void flushWork(int current) {
    System.out.println(Thread.currentThread().getName() + " reset " + current + " to " + Decrementer.MAX_SIZE);
    System.out.println('------------------------------------------------------------------------------------');
    Thread.sleep(4217);
}

private void doWork(int current) {
    System.out.println(Thread.currentThread().getName() + " at counter " + current);
    Thread.sleep(62);
}
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/40440660

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档