【问题标题】:Understanding the behaviour of Synchronized了解 Synchronized 的行为
【发布时间】:2011-12-13 09:07:52
【问题描述】:

我正在努力加深对synchronized 调用期间发出的锁定范围的理解。

例如:

class CopyOnReadList<T> {

    private final List<T> items = new ArrayList<T>();

    public void add(T item) {
        items.add(item);
    }

    public List<T> makeSnapshot() {
        List<T> copy = new ArrayList<T>();
        synchronized (items) {
            // Make a copy while holding the lock.
            for (T t : items) copy.add(t);
        }
        return copy;
    }

}

(代码亲切地从this excellent answer借来)

在这段代码sn-p中,一个线程可以调用add,而另一个线程调用makeSnapshot吗?即,synchronized (items) 创建的锁会影响对items 的所有尝试读取,还是仅影响通过makeSnapshot() 方法尝试的读取?

原帖实际上在add方法中使用了synchonized锁:

public void add(T item) {
    synchronized (items) {
        // Add item while holding the lock.
        items.add(item);
    }
}

去掉这个有什么副作用?

【问题讨论】:

  • 如果您从 add 方法中删除 synchronized ,那么当您调用 makeSnapshot 时,您无法保证all 对其他线程添加的所有项目进行“快照”。因此,据我所知,删除 synchronized 调用的副作用是现在代码已损坏。除此之外,甚至可能达到不一致的状态......

标签: java concurrency


【解决方案1】:

它只影响那些在 makeSnapshot() 中尝试的方法,或者更一般地说,任何其他具有 synchronized(items) 阻塞的方法(这意味着它会尝试获取 items 对象的锁定并阻塞直到可能)。

从 add() 方法中删除同步块的副作用是 add() 不会尝试对 items 对象进行同步,因此将允许并发修改,包括在 makeSnapshot() 执行时。

如果在 add() 中不同步,您可以让其他线程在创建快照时将元素添加到项目集合。

【讨论】:

    【解决方案2】:

    在这段代码sn-p中,可以一个线程调用add而另一个线程调用吗 制作快照?

    当然 - 任何一种方法都可能因ConcurrentModificationException 而失败,或者列表的内容可能已损坏。

    同步(项目)创建的锁是否影响所有尝试 读取项目,或仅通过 makeSnapshot() 尝试的项目 方法?

    两者都没有。锁对对象items 的行为没有任何影响,仅对与其同步的块或方法 - 即确保没有两个线程可以同时执行这些块或方法中的任何一个。

    【讨论】:

      【解决方案3】:

      一个线程调用 add 而另一个调用 makeSnapshot 可以吗?

      是的。 synchronized 确保任何其他线程不能在同一个对象上输入另一个也同步的代码块(在这种情况下为CopyOnReadList)。由于您没有同步 add 方法,因此多个线程可以同时调用add,即使一个线程正在执行makeSnapshot

      通过删除 add 方法上的同步,您使代码成为非线程安全的,因为 ArrayList 不是线程安全的。

      经验法则是:对共享可变状态的每次访问(读取或写入)都必须在同一个锁上同步。

      【讨论】:

        猜你喜欢
        • 2023-03-24
        • 1970-01-01
        • 2017-11-08
        • 2014-05-29
        • 1970-01-01
        • 2016-09-28
        • 2019-10-08
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多