同步列表



假设我有这样的代码块:

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对象,而迭代当前正在运行?

是。看看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),这意味着iterate()方法中的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();
}

是的,你是对的。returnFirst将不会运行,直到iterate完成。

相关内容

  • 没有找到相关文章