所以我参加了这场赛马比赛,当一匹马到达终点线时,我引用了一种到达方法。假设我有10个线程,每匹马一个,第一匹到达的马确实在调用'到达':
public class FinishingLine {
List arrivals;
public FinishingLine() {
arrivals = new ArrayList<Horse>();
}
public synchronized void arrive(Horse hourse) {
arrivals.add(hourse);
}
}
Ofc我将到达方法设置为同步但我不完全理解如果它不同步会发生什么,教授只是说它不安全。
我想更好地理解的另一件事是如何决定第一个线程完成后哪个线程?在第一个线程完成“到达”并且方法解锁后,下一个线程将运行?
答案 0 :(得分:1)
1)未定义行为是什么,但你应该假设它不是你想要它以你可以依赖的任何方式做的事情。
如果两个线程同时尝试添加,则可能会添加两个元素(按任意顺序),只添加一个元素,或者甚至两个元素都不添加。
Javadoc的相关引用是:
请注意,此实施未同步。如果多个线程同时访问ArrayList实例,并且至少有一个线程在结构上修改了列表,则必须在外部进行同步。 (结构修改是添加或删除一个或多个元素的任何操作,或显式调整后备数组的大小;仅设置元素的值不是结构修改。)
2)这取决于操作系统如何安排线程。对于常规同步块,不保证“公平”(在到达顺序中执行),尽管某些类(Semaphore是一个)可以让您选择公平的执行顺序。
e.g。您可以使用信号量实现公平的执行顺序:
public class FinishingLine {
List arrivals;
final Semaphore semaphore = new Semaphore(1, true);
public FinishingLine() {
arrivals = new ArrayList<Horse>();
}
public void arrive(Horse hourse) {
semaphore.acquire();
try {
arrivals.add(hourse);
} finally {
semaphore.release();
}
}
}
但是,使用fair blocking queue来处理并发访问会更容易:
public class FinishingLine {
final BlockingQueue queue = new ArrayBlockingQueue(NUM_HORSES, true);
public void arrive(Horse hourse) {
queue.add(hourse);
}
}