在列表上同步
Synchronize on List
假设我有这个代码块:
List<Integer> lst = Collections.synchronizedCollection(new ArrayList<>());
而我有以下两种方法:
public Integer returnFirst() {
lst.get(0);
}
public void iterate() {
synchronized(lst) {
Iterator i = lst.iterator();
while (i.hasNext()) {
System.out.println(i);
}
}
}
假设一个线程调用iterate(),那么另一个线程调用returnFirst()。 returnFirst() 是否会被阻止,因为您正在迭代中同步 List 对象,并且迭代当前为 运行?
是的,你是对的。在 iterate
完成之前,returnFirst
不会 运行。
是的。
看看 SynchronizedCollection
构造函数和 SynchronizedList#get
方法:
SynchronizedCollection(Collection<E> c) {
this.c = Objects.requireNonNull(c);
mutex = this;
}
public E get(int index) {
synchronized (mutex) {return list.get(index);}
}
你可以看到用于控制并发访问的内部互斥体实际上是对象本身(mutex = this
),这意味着你的[=18=中的lst.get(0)
和synchronized(LST)
] 方法竞争同一个锁:对象本身。
此外,您的代码将无法编译,请将 synchronizedCollection
替换为 synchronizedList
。
简单代码测试:
public static void main(String[] args) throws InterruptedException {
List<Integer> list = Collections.synchronizedList(new ArrayList<>());
list.add(1);
new Thread(() -> {
try {
synchronized(list) {
Thread.sleep(5000);
Iterator i = list.iterator();
while (i.hasNext()) {
System.out.println(i.next());
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
Thread.sleep(100);
new Thread(() -> {
// It will block for 5 seconds and then output
System.out.println(list.get(0));
}).start();
}
假设我有这个代码块:
List<Integer> lst = Collections.synchronizedCollection(new ArrayList<>());
而我有以下两种方法:
public Integer returnFirst() {
lst.get(0);
}
public void iterate() {
synchronized(lst) {
Iterator i = lst.iterator();
while (i.hasNext()) {
System.out.println(i);
}
}
}
假设一个线程调用iterate(),那么另一个线程调用returnFirst()。 returnFirst() 是否会被阻止,因为您正在迭代中同步 List 对象,并且迭代当前为 运行?
是的,你是对的。在 iterate
完成之前,returnFirst
不会 运行。
是的。
看看 SynchronizedCollection
构造函数和 SynchronizedList#get
方法:
SynchronizedCollection(Collection<E> c) {
this.c = Objects.requireNonNull(c);
mutex = this;
}
public E get(int index) {
synchronized (mutex) {return list.get(index);}
}
你可以看到用于控制并发访问的内部互斥体实际上是对象本身(mutex = this
),这意味着你的[=18=中的lst.get(0)
和synchronized(LST)
] 方法竞争同一个锁:对象本身。
此外,您的代码将无法编译,请将 synchronizedCollection
替换为 synchronizedList
。
简单代码测试:
public static void main(String[] args) throws InterruptedException {
List<Integer> list = Collections.synchronizedList(new ArrayList<>());
list.add(1);
new Thread(() -> {
try {
synchronized(list) {
Thread.sleep(5000);
Iterator i = list.iterator();
while (i.hasNext()) {
System.out.println(i.next());
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
Thread.sleep(100);
new Thread(() -> {
// It will block for 5 seconds and then output
System.out.println(list.get(0));
}).start();
}