以不同步的方式改变对象的两个不同部分不安全吗?
假设我有一个相对简单的对象,具有两个属性:
@Data
public class MyObject {
public Integer a;
public Integer b;
}
我可以安全地在某个线程中改变 a 并在其他线程中安全地改变 b 吗?例如,这段代码不会受到竞争条件的影响吗?
public MyObject compute() {
MyObject newObj = new MyObject();
List<Runnable> tasks = new ArrayList<>();
Runnable computeATask = () -> {
Integer a = computeA();
newObj.setA(a);
};
Runnable computeBTask = () -> {
Integer b = computeB();
newObj.setB(b);
};
tasks.add(computeATask);
tasks.add(computeBTask);
tasks.stream().parallel().forEach(Runnable::run);
return newObj;
}
Lets say I have a relatively simple object with two properties :
@Data
public class MyObject {
public Integer a;
public Integer b;
}
can I safely mutate a in some thread and b in some other thread safely ? for example, would this code be safe from race conditions ?
public MyObject compute() {
MyObject newObj = new MyObject();
List<Runnable> tasks = new ArrayList<>();
Runnable computeATask = () -> {
Integer a = computeA();
newObj.setA(a);
};
Runnable computeBTask = () -> {
Integer b = computeB();
newObj.setB(b);
};
tasks.add(computeATask);
tasks.add(computeBTask);
tasks.stream().parallel().forEach(Runnable::run);
return newObj;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这是在 JLS,§17.6 中指定的。单词撕裂:
因此,在您的示例中,
a
可能由与b
不同的线程编写,这一事实不会产生任何数据争用。但它仍然需要一个线程安全的机制来读取结果。在您的示例中,并行流保证启动线程可以在
forEach
返回后安全地读取两个变量。您的示例可以简化为
但推荐的模式是首先执行计算,然后构造对象,然后可以将其设计为不可变对象。
这样,您就可以确保看到
MyObject
的任何线程都将看到一致的字段值,无论其余应用程序中发生什么情况。This is specified in JLS, §17.6. Word Tearing:
So the fact that
a
might written by a different thread thanb
in your example, does not create any data race.But it still requires a thread safe mechanism to read the result. In your example, it’s the parallel stream which guarantees that the initiating thread can safely read the two variables after
forEach
returned.You example can be simplified to
But the recommended pattern would be to execute the calculation first, followed by constructing the object, which can be designed as immutable object then.
This way, you can be sure that any thread seeing the
MyObject
will see consistent values for the fields, regardless of what happens in the remaining application.