首页 > 解决方案 > 使用 Java 锁时出现竞争条件的可能性

问题描述

我编写了一个 Java 类,有人查看了代码并坚持认为方法中可能存在竞争条件calculate。这是类代码的简化版本:

public class MyClass {
    private List<Integer> list;
    private final ReadWriteLock lock;

    public MyClass() {
        list = new ArrayList<>();
        lock = new ReentrantReadWriteLock();
    }

    public void add(Integer integer) {
        lock.writeLock().lock();
        try {
            list.add(integer);
        } finally {
            lock.writeLock().unlock();
        }
    }

    public void deleteAll() {
        lock.writeLock().lock();
        try {
            list.clear();
        } finally {
            lock.writeLock().unlock();
        }
    }

    public Integer calculate() {
        List<Integer> newList = new ArrayList<>();
        Integer result = 0;

        lock.readLock().lock();
        try {
            list.forEach(integer -> {
                // calculation logic that reads values from 'list' and adds only a subset of elements from 'list' in 'newList'
            });
        } finally {
            lock.readLock().unlock();
        }

        setList(newList);
        return result;
    }

    private void setList(List<Integer> newList) {
        lock.writeLock().lock();
        try {
            list = newList;
        } finally {
            lock.writeLock().unlock();
        }
    }
}

现在我的问题是:

在这种方法中真的会发生竞争条件吗?如果是这样,我该如何解决它(使用锁或使用任何其他方法来使类线程安全)?

任何意见,将不胜感激。

标签: javamultithreadingconcurrencyjava-8thread-safety

解决方案


newList创建和调用之间存在时间间隔setList(newList)setList(newList)我们可以假设这个时间间隔是任意长的,并且当它持续时一切都可能发生,例如另一个线程添加了一个必须保留的对象,但是当调用删除list该新对象时它将丢失。

实际上,该方法calculate正在修改并且应该在写锁下完成所有工作。


推荐阅读