首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >线程有自己的数据副本吗?

线程有自己的数据副本吗?
EN

Stack Overflow用户
提问于 2020-04-15 17:45:58
回答 2查看 559关注 0票数 0

我在某个地方读到,每个线程都有自己的共享状态副本,即使我使用同步或锁来修改变量,如何保证更改的状态将被刷新到主内存中,而不是在线程自己的缓存内存中。

我知道不稳定的保证,并证明上述情况是合理的,甚至我知道同步也是合理的。

同步如何保证在主内存而不是线程缓存内存中发生更改值。

Ex螺纹1

代码语言:javascript
复制
synchronized(this)
{
int a = 0;
a = 5;
}  ----> the value might got changed in thread's cache memory another thread entering the block could read a value as 0

volatilte int a = 0;
a = 5; ----> another executing thread will read a values as 5
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-04-15 21:57:15

在考虑java中的多线程代码时,您必须从happens-before的角度进行推理,这是JLS所使用的,也是您应该使用的。句号。

就您的示例而言,您将volatilesynchronized放在一起,就好像它们做了相同的事情--它们没有。即使是您的示例也失败了,因为“其他”线程要查看一个有保证的a = 5,它必须在相同的锁上同步,而您没有同步。jc应激测试证明您是错误的(我会让您知道如何准确地运行这一点)

代码语言:javascript
复制
@JCStressTest
@State
@Outcome(id = "1, 0", expect = Expect.ACCEPTABLE_INTERESTING, desc = "SURPRISE")
@Outcome(id = "0, 1", expect = Expect.ACCEPTABLE, desc = "whatever")
@Outcome(id = "0, 0", expect = Expect.ACCEPTABLE, desc = "whatever")
@Outcome(id = "1, 1", expect = Expect.ACCEPTABLE, desc = "whatever")
public class DifferentSynchronizedObjects {

    int x, y;
    private Object lock = new Object();

    @Actor
    public void actor1() {
        synchronized (lock) {
            x = 1;
            y = 1;
        }
    }

    @Actor
    public void actor2(II_Result r) {
        r.r1 = x;
        r.r2 = y;
    }
} 

即使您不理解代码,它的主要“卖点”是:

代码语言:javascript
复制
@Outcome(id = "1, 0", expect = Expect.ACCEPTABLE_INTERESTING, desc = "SURPRISE")

您可以将其读为:“当您在同步(锁){.}中时,其他线程出现并读取x和y”。这个阅读线程看到了1, 0 (x = 1y = 0),现在考虑一下它。您在synchronized块中,为什么有些线程读取x = 1y = 0,难道不是“受保护”吗?不,你没有。如果你运行这个-你会得到1, 0

编辑以回答注释

您认为您是在保护xy的通信--但是由于JLS没有提供这样的保证,这是您对事物的理解,这是错误的。就这么简单。您真正得到的唯一保护是,如果您的作者和读者使用相同的锁。

优化器可能会“看到”您只在方法中使用该lock,并将该代码转换为(至少在理论上):

代码语言:javascript
复制
@Actor
public void actor1() {

    Object lock = new Object(); // < --  make lock local       

    synchronized (lock) {
        x = 1;
        y = 1;
    }
}

既然lock现在是一个方法的局部,那么拥有它又有什么意义呢?没有人能够访问它,只需将其完全删除。因此,您将得到一个完全不受保护的代码,它执行两个独立的写操作。

结论是:你不遵守JLS给你的规则--做好准备,得到奇怪的结果。

票数 4
EN

Stack Overflow用户

发布于 2020-04-15 18:14:20

如果不使用synchronized关键字(或易失性关键字),就不能保证当一个线程更改与其他线程共享的变量的值时,其他线程可以看到更改的值。不能保证由一个线程保存在CPU寄存器中的变量何时“提交”到主内存,也不能保证其他线程何时“刷新”主内存中保存在CPU寄存器中的变量。

使用synchronized关键字,当线程进入同步块时,它将刷新线程可见的所有变量的值(在同一个锁/对象上)。当线程退出同步块时,对线程可见的变量以及同一锁的所有更改都将被推送/更新到主内存。实际上,它与volatile的工作是一样的。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61235213

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档