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);
}
}