Java 由不同线程写入/读取的基本类字段变量

Java 由不同线程写入/读取的基本类字段变量,java,multithreading,Java,Multithreading,作为我承担的一个项目的一部分,我得到了以下类(重写/重命名以简化示例): 该代码本质上提供了校准方法,可以临时更改线程正在执行的工作。但是,这使用了一个基本布尔值,这让我感到惊讶,因为两个线程都在写入变量 这不需要某种同步吗?我想应该是这样的,但不知怎么的,它工作正常。如果不需要同步,为什么 编辑2:这不是我的代码,是别人做的-我正在修复它!:) 安全性或活性故障很少发生,但一旦发生故障,总是在生产中负载过重时发生 最近,我尝试实验一些竞争条件,以说明正确引入同步块的必要性。但大多数时候,我必须

作为我承担的一个项目的一部分,我得到了以下类(重写/重命名以简化示例):

该代码本质上提供了校准方法,可以临时更改线程正在执行的工作。但是,这使用了一个基本布尔值,这让我感到惊讶,因为两个线程都在写入变量

这不需要某种同步吗?我想应该是这样的,但不知怎么的,它工作正常。如果不需要同步,为什么


编辑2:这不是我的代码,是别人做的-我正在修复它!:)

安全性或活性故障很少发生,但一旦发生故障,总是在生产中负载过重时发生

最近,我尝试实验一些竞争条件,以说明正确引入同步块的必要性。但大多数时候,我必须非常谨慎地设计它,以使它再次发生

您的演示中有几个问题需要解决,例如同步问题


正如@St.Antario所指出的,当线程被扩展(作为父类)时,最好不要在构造函数中启动线程,当子类尚未完全初始化时,线程将访问子类中重写的某些方法,这可能是危险的。

安全性或活动性失败很少发生,但当它发生时,总是在生产中负载过重时发生

最近,我尝试实验一些竞争条件,以说明正确引入同步块的必要性。但大多数时候,我必须非常谨慎地设计它,以使它再次发生

您的演示中有几个问题需要解决,例如同步问题


正如@St.Antario所指出的,您最好不要在构造函数中启动线程,当它被扩展(作为父类)时,当子类尚未完全初始化时,线程将访问子类中重写的某些方法,这可能是危险的。

它现在可能正在工作,但这样做并不正确。

基本数据类型不是线程安全的,没有什么可以证明它是正确的。这就是为什么JDK提供了
原子类作为原始数据类型线程安全的包装器。毫无疑问,我会将
bool
替换为
AtomicBoolean
,否则给定的代码注定会失败


查看此显示了与多线程环境中使用的原语不一致的测试结果。

它现在可能正在工作,但并不正确。

基本数据类型不是线程安全的,没有什么可以证明它是正确的。这就是为什么JDK提供了
原子类作为原始数据类型线程安全的包装器。毫无疑问,我会将
bool
替换为
AtomicBoolean
,否则给定的代码注定会失败


请查看这篇文章,其中显示了与多线程环境中使用的原语不一致的测试结果。

如果不了解所发生情况的上下文,就很难判断代码是否正确

如果布尔值为真,第一个线程进入第一个块,中间的另一个线程将它更改为false,行吗?是否允许两个线程在第一个块中运行,即使其中一个线程将其更改为false,而另一个线程仍在

true
块中运行?在这种情况下,您需要在块本身周围有更多的同步构造,而不仅仅是简单的布尔检查

关于原语上的同步,您应该明确地做一件事,将其声明为
private volatile bool=false这确保每个线程不会保留其值可能过期的变量的本地缓存副本


如果希望对变量本身进行线程安全更新,您还可以选择使用
AtomicBoolean
,但我怀疑这是线程安全问题中最小的一个。

如果不了解发生的情况,很难判断代码是否正确

如果布尔值为真,第一个线程进入第一个块,中间的另一个线程将它更改为false,行吗?是否允许两个线程在第一个块中运行,即使其中一个线程将其更改为false,而另一个线程仍在

true
块中运行?在这种情况下,您需要在块本身周围有更多的同步构造,而不仅仅是简单的布尔检查

关于原语上的同步,您应该明确地做一件事,将其声明为
private volatile bool=false这确保每个线程不会保留其值可能过期的变量的本地缓存副本

如果希望对变量本身进行线程安全更新,您还可以选择使用原子布尔,但我怀疑这是线程安全问题中最小的一个。

其他线程调用calibrate()方法

并发问题可能会导致语义问题

当内部线程将布尔变量重置为false,同时或在关闭期间,外部线程在
if
语句结束之前将
bool
变量更新为true时,会发生什么情况。您可能希望执行
常规工作
,但相反,您将执行
一些不同的工作
,因为在重新检查
条件时,在
之前,外线程将值更改回
true

其他线程调用calibrate()方法

public class Temp {
    private boolean bool = false;

    // edit 1: calibrate called by other threads in the program
    public void calibrate() {
        bool = true;
    }

    public Temp() {
       thread.start(); 
    }

    private final Thread thread = new Thread(new Runnable() {
        @Override
        public void run() {
            while(true) {
                if(bool) {
                    // do some different work
                    bool = false;
                }
                else {
                    // do regular work
                }
            }
        }
    });
}