Java 理解同步的行为

Java 理解同步的行为,java,concurrency,Java,Concurrency,我试图提高对同步调用期间发出的锁的范围的理解 例如: 删除此项的副作用是什么?它只影响在makeSnapshot()中尝试的那些方法,或者更一般地说,影响已同步(项)块的任何其他方法(这意味着它将尝试获取项对象和块的锁,直到可能为止) 从add()方法中删除synchronized block的副作用是,add()将不会尝试对items对象进行同步,因此将允许并发修改,包括在makeSnapshot()执行时进行修改 如果没有在add()中同步,则可以让其他线程在创建快照时将元素添加到items

我试图提高对
同步调用期间发出的锁的范围的理解

例如:


删除此项的副作用是什么?

它只影响在makeSnapshot()中尝试的那些方法,或者更一般地说,影响已同步(项)块的任何其他方法(这意味着它将尝试获取项对象和块的锁,直到可能为止)

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

如果没有在add()中同步,则可以让其他线程在创建快照时将元素添加到items集合

在这个代码段中,一个线程可以在另一个线程调用add时调用add吗 快照

当然-然后,其中任何一个方法都可能失败,出现
ConcurrentModificationException
,或者列表的内容可能已损坏

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

都不是。锁对对象<代码>项
的行为没有任何影响,仅对在其上snychroning的块或方法有影响-即确保没有两个线程可以同时执行这些块或方法中的任何一个

一个线程可以在另一个线程调用makeSnapshot时调用add吗

synchronized
确保任何其他线程都不能在同一对象(在本例中为
CopyOnReadList
)上输入另一个同样同步的代码块。由于尚未同步add方法,因此即使有一个线程正在执行
makeSnapshot
,多个线程也可以同时调用
add

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

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

如果从add方法中删除synchronized,那么在调用makeSnapshot时,根本不能保证对其他线程添加的所有项进行“快照”。因此,就我所见,删除同步调用的副作用是现在代码被破坏了。除此之外,它甚至可能达到一个不一致的状态。。。
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;
    }

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