以下是有关如何防止竞争条件的答案。 What is a race condition?不可变对象如何有助于防止竞争条件
最好的事情是创建无副作用和无状态 功能,使用immutables尽可能。但这并不总是 可能。因此,使用java.util.concurrent.atomic,并发数据 结构,适当的同步和基于角色的并发将帮助 。
这个答案说尽可能地使用immutables。我很困惑不变的对象如何防止竞争条件。
以下是有关如何防止竞争条件的答案。 What is a race condition?不可变对象如何有助于防止竞争条件
最好的事情是创建无副作用和无状态 功能,使用immutables尽可能。但这并不总是 可能。因此,使用java.util.concurrent.atomic,并发数据 结构,适当的同步和基于角色的并发将帮助 。
这个答案说尽可能地使用immutables。我很困惑不变的对象如何防止竞争条件。
只有当至少有一个线程被允许写/改变实例的状态时才会出现竞争条件。 不可变实例只读,它们的状态不能被改变,因此,所有线程只读的对象的状态,并且看到相同的值(一个或多个)
甲data race时发生“两个或多个线程...同时访问相同的内存位置,并且至少有一个访问用于写入,并且这些线程不使用任何排他锁来控制对该内存的访问。“
如果数据不可变,就不会有数据竞争,因为可能没有写入权限。
另外,Java Memory Model guarantees:
一旦对象被构造中,分配给在构造最终字段中的值将是可见的所有其它线程不同步。
当计算结果取决于评估表达式和语句的顺序时,会出现竞争条件。
如果对表达式和语句的评估改变状态,产生副作用,结果可能会有所不同。
如果代码中的所有内容都是不可变的,那么在对表达式和语句进行评估时,不会改变状态,也不会产生副作用。因此评估顺序不会影响最终结果。
考虑下面的代码:
Map<String, Integer> map = Collections.singletonMap("key", 0);
public void increment() {
int val = map.get("key);
map.put("key", val + 1);
}
如果两个线程执行方法increment()
的每个语句同时,同时读同一价值0
两者放在同一增加值1
到map
。因此结果将是1
。
如果两个线程(偶然)将执行所有语句连续一个线程会读取值0
,并把价值1
而其他线程会读取值1
,把价值2
。
现在,如果地图将是不可改变的,两个线程将执行以下方法:
public void logMap() {
System.out.println("Key has value " + map.get("key"));
}
结果将始终是相同的,因为没有副作用(除了由所做的更改System.out.println)影响计算。
如果一个对象是不可变的,那么多少个线程访问它并不重要。 –
如果您无法修改内容,则不能进行并发修改。 – user2357112