当前位置: 首页 > 知识库问答 >
问题:

如果一个可变变量是从两个线程写入的,会发生什么?

江琦
2023-03-14

在实践中考虑java并发的片段

@ThreadSafe
public class SynchronizedInteger{
    @GuardedBy("this") private int value;

    public synchronized int getValue() {
        return value;
    }

    public synchronized void setValue(int value) {
        this.value = value;
    }
}

同一本书的摘录-

考虑易失性变量的一个好方法是想象它们的行为大致类似于上面清单中的同步整数类,用调用get和set来替换易失性变量的读写。然而,访问易失性变量不执行锁定,因此不会导致执行线程阻塞,这使得易失性变量成为比同步更轻量级的同步机制。

线程限制的一种特殊情况适用于可变变量。对共享的易失性变量执行读-修改-写操作是安全的,只要确保该易失性变量仅从单个线程写入。

因此,如果将上述类中的实例变量设置为volatile,然后删除synchronized关键字,那么假设有3个线程

线程A

既然volatile变量现在是从两个线程写入的,为什么对这个共享的volatile变量执行读-修改-写操作是不安全的?

共有3个答案

章昆琦
2023-03-14

如果在不使用任何同步构造的情况下从多个线程编写volatile变量,则必然会出现数据不一致错误。

对于原子操作,在单写线程和多读线程的情况下,使用不同步的可变变量。

Volatile确保从主内存而不是线程缓存中获取变量值。它可以安全地用于单写和多读操作。

使用原子变量或同步或锁定API从多个线程更新和读取变量。

参考相关SE问题:

“线程安全”代码是什么意思?

安建木
2023-03-14

这是因为对易失性变量的读-修改-写操作不是原子的。

r1 = v;
r2 = r1 + 1;
v = r2;

因此,如果有两个线程各自执行一次此操作,则可能会导致变量只递增一次,因为它们都读取旧值。这就是为什么它不安全的一个例子。

在您的示例中,如果您删除了同步,使字段变得不稳定,并且在基于getValue返回的条件逻辑之后有两个线程调用setValue,那么这将是不安全的-该值可能已被另一个线程修改。

如果你想进行原子操作,可以看看java。util。同时发生的原子包。

潘鸿文
2023-03-14

关键字volatile用于确保其他线程会看到对对象所做的更改。这并不强制要求在操作完成之前,对对象执行非原子操作,而不会受到其他线程的干扰。为了实现这一点,您需要关键字synchronized

 类似资料:
  • 问题内容: 我试图了解变量如何在python中工作。说我有一个对象存储在变量中: 如果我分配给,则它们都指向同一个对象: 但是,如果我重新分配或,那就不再正确了: 这两个变量现在具有不同的值: 我不明白为什么变量现在不同。为什么不再是真的?有人可以解释发生了什么吗? 问题答案: Python具有引用 对象的 名称 。对象与名称分开存在,名称与它们引用的对象分开存在。 __ 在为“名称分配名称”时,

  • 问题内容: 这是我学习python的第二天(我了解C ++和一些OOP的基础知识),并且我对python中的变量有些困惑。 这是我目前对它们的了解: Python变量是对对象(可变或不可变)的引用(或指针?)。当我们有类似的内容时,不可变对象将在内存中的某个位置创建,而名称- 对象引用对将在某个命名空间中创建。当我们拥有时,不会复制任何内容,但是现在两个变量都引用相同的对象,并被添加到相同的名称空

  • 问题 下面的代码显示,当影响一个数组到另一个数组时,这两个数组变得相互依赖。 我想知道为什么这与类型不同,因为如果我们有以下内容: 两个变量和引用的是同一个字符串,所以更改一个会影响另一个。

  • 我有一个疑问相对于UI线程和其他线程之间的concurrency。 Ui主线程更新不同变量的值:-flol-long-boolean 我还有另一个线程,它读取同一个变量,并用它执行一些逻辑操作(不编辑它的值),然后用这个操作的结果发送本地广播消息。 是否存在并发问题???我必须使用同步方法和原子变量,否则就无关紧要了? 我反思这个问题,因为没有浮点基元的原子变量,也因为我害怕用错误的代码阻止Ui线

  • 问题内容: 我有两个线程。可以调用修改变量的类的update方法。另一个调用读取该变量的类的update方法。只有一个线程写入,一个(或多个)线程读取该变量。由于我是多线程技术的新手,我需要在并发方面做什么? 谢谢, 问题答案: 如果有且仅有一个写线程,你可以逃脱使得它。否则,请查看答案。 仅在只有一个写线程的情况下才起作用,因为只有一个写线程,因此它始终具有的正确值。

  • 我正试着用铁锈的雪球词干分析器板条箱来词干。这应该很简单,但借用检查器一直拒绝我的代码: 借用检查器说我在