RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 811050
Accepted
Direct
Direct
Asked:2020-04-08 04:27:19 +0000 UTC2020-04-08 04:27:19 +0000 UTC 2020-04-08 04:27:19 +0000 UTC

同步变化的价值可见性

  • 772

据我们所知,通过更改volatile变量,我们仍然确信将读取它的其他线程将接收到新值。这样做的原因很清楚:变量值没有被缓存(当然还有更多的事情要做,但要点是这里的重点)。所以我不清楚,但是non-volatile同步期间变量更改的可见性会发生什么?

一个可靠的消息来源说:

同步强制将数据写入主存,如果一个字段被同步方法或块完全保护,volatile则不需要声明它以进行并发访问。

所以,问题是:这是怎么发生的,为什么我们现在不需要关键字volatile?我们需要synchronizedgetter 和 setter,还是读同步就足够了?或者也许只是写下来?

让我解释一下关于 getter 和 setter 的问题的一部分:
让代码:

class A {
    int n=1;
    public void change(){
        while (!Thread.interrupted())
            synchronized (this){
                n=3*n+4;
            }
    } 
}

在main(String[] args)与类相同的包中A:

A a = new A();
new Thread(a::change).start();
TimeUnit.SECONDS.sleep(10);
System.out.println(a.n);

这里出现了问题。
现在让我们忘记变量n可能会溢出,然后我们在 10 秒内休眠后再次变为等于 1。忘记当我们读取时n它可能处于某种“不稳定”状态。
那么,方法中是否有足够的同步change()?它是否保证推入main memory我们的变量n?那些。事实上,问题是这样的:是否真的不会发生在 10 秒的睡眠后a.n我们得到 1 的情况,因为该字段的值仍在缓存中?

如果您将最后一行更改main(String[] args)为:

synchronized (a){
    System.out.println(a.n);
}

现在一切都很好,更改的可见性不会有问题吗?同步机制的这方面是如何工作的?那些。change()没有推入main memory,但同步读取所有内容都被立即推入?...或者change()同步是否足够?


在答案的附录中,我将非常感谢看到 Java 文档(翻译成俄语)中的引用以及指向它们的链接。


这里和这里都有重要的想法,但我想得到一个不同问题的答案。

java
  • 1 1 个回答
  • 10 Views

1 个回答

  • Voted
  1. Best Answer
    Sergey Gornostaev
    2020-04-08T14:16:48Z2020-04-08T14:16:48Z

    修饰符volatile不仅synchronized解决了缓存问题。在多线程编程中仍然需要考虑很多细微差别。例如,重新排序. 在许多情况下,对变量(对象字段、静态字段和数组元素)的访问可以按照与程序中指定的顺序不同的顺序执行。为了优化,编译器可以自由地安排指令。在某些情况下,处理器可能会以不同的顺序执行指令。数据可以在寄存器、处理器高速缓存和主存储器之间以不同于程序中指定的顺序移动。但是JMM通过设置屏障来确保在同步块中保留发生之前的关系在获取和释放锁时。“同步”这个词的语义不言自明。对变量执行同步访问的线程会同步其状态。但是只有在每个人都同步的情况下,才能为每个人真正更新变量状态。

    另外,别忘了同步不仅是为了解决可见性问题,也是为了解决原子性问题。如果一个线程在访问该字段时捕获了锁,而另一个线程甚至没有尝试捕获它并因此检查其状态,则锁定没有意义,程序将破坏状态。

    PS,而不是文档的链接,我将提供一个人的报告的链接,该人的名字已成为该地区家喻户晓的名字。

    Aleksey Shipilёv - Java 内存模型语用学,第 1 部分
    Aleksey Shipilёv - Java 内存模型语用学,第 2 部分
    Aleksey Shipilё - JMM 学位

    • 6

相关问题

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    是否可以在 C++ 中继承类 <---> 结构?

    • 2 个回答
  • Marko Smith

    这种神经网络架构适合文本分类吗?

    • 1 个回答
  • Marko Smith

    为什么分配的工作方式不同?

    • 3 个回答
  • Marko Smith

    控制台中的光标坐标

    • 1 个回答
  • Marko Smith

    如何在 C++ 中删除类的实例?

    • 4 个回答
  • Marko Smith

    点是否属于线段的问题

    • 2 个回答
  • Marko Smith

    json结构错误

    • 1 个回答
  • Marko Smith

    ServiceWorker 中的“获取”事件

    • 1 个回答
  • Marko Smith

    c ++控制台应用程序exe文件[重复]

    • 1 个回答
  • Marko Smith

    按多列从sql表中选择

    • 1 个回答
  • Martin Hope
    Alexandr_TT 圣诞树动画 2020-12-23 00:38:08 +0000 UTC
  • Martin Hope
    Suvitruf - Andrei Apanasik 什么是空? 2020-08-21 01:48:09 +0000 UTC
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5