微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

java – 使用volatile和synchronized时,刷新或发布到各种线程的内存范围是什么?

这个问题仅涉及内存可见性,不会发生在之前和发生之后. Java中有四种方法可以保证一个线程中的内存更改对另一个线程可见. (参考 http://gee.cs.oswego.edu/dl/cpj/jmm.html)

>写入线程释放同步锁,读取线程随后获取相同的同步锁.
>如果一个字段被声明为volatile,则在写入程序线程执行任何进一步的内存操作之前,写入该文件的任何值都会被刷新并使其可见(即,为了手头的目的,它会立即刷新).
>线程第一次访问对象的字段时,它会看到字段的初始值或自某个其他线程写入的值.
>当一个线程终止时,所有写入的变量都被刷新到主存储器.

根据Java Concurrency in Practice,关于这些问题的圣经:

The visibility effects of volatile variables extend beyond the value of the volatile variable itself. When thread A writes to a volatile variable and subsequently thread B reads that same variable,the values of all variables that were visible to A prior to writing to the volatile variable become visible to B after readin the volatile variable.

挥发性的问题

这是否意味着JVM实际上跟踪了易失性变量读写,以便知道如何将内存从A刷新到B而不是A到C?所以A写入变量,后来C从变量读取,然后B从变量读取,刷新是在A和B以及A和C之间的每个线程基础上完成的,而不是B和C?或者,它是否暗示所有缓存的内存都被刷新,无论线程如何?只是刷新了volatile变量,还是所有缓存的内存?

同步问题

对于synchronized关键字刷新,它表示只有锁内部更新的内存才能保证发布到其他线程.这意味着在下面的代码中,两个运行method()的线程,保留synchronized块会将staticVar2刷新到另一个线程,但不是staticVar1,这是正确的吗?

此外,在method2()中,如果另一个线程正在执行method(),则可以导致在发生问题之前发生 – 遇到问题.但是,问题在于可见性.如果线程A执行方法,那么后来的线程B执行method2(),是从A到B发布的staticVar2的值,即使这两个线程没有通过同一个锁同步?

static int staticVar1,staticVar2;
void method() {
    staticVar1++;
    synchronized (lock) {
        staticVar2++;
    }
}
void method2() {
    synchronized (differentLock) {
        staticVar2++;
    }
}

静态问题

在我看来,如果staticVar1永远不会更新到其他线程,那么任何程序中的所有静态变量都需要一个volatile声明,或者只能在synchronized块中访问.这似乎相当苛刻,但它是否正确?我确定在我的时间里看到了很多不同步的静态变量.

综上所述

>易失性读写会将所有内存刷新到所有线程,还是仅在两个访问线程之间?无论哪个答案,是所有内存都刷新了还是只有易变量?
>退出同步块时,或者只是块内更改的内存,是否刷新了内存?如果没有刷新所有内存,则线程同步的锁定对象是否必须相同才能看到该值(即锁定对象是否对内存可见性有任何影响)?
>是否必须同步两个线程访问的所有静态变量?

解决方法

内存方面没有范围限制.当您具有读或写屏障时,它适用于所有内存读/写.

我在哪里看到了内存映射的限制.当你的内存映射文件时,你必须要小心如何使这个可用于另一个线程,因为这个新的内存映射可能在另一个线程中不可见,立即导致BUS错误(以及JVM崩溃)这似乎是一个操作系统错误,因为最新版本的Linux和Windows似乎没有这个问题.

That implies that in the following code,two threads running method(),leaving the synchronized block will flush staticVar2 to the other thread,but not staticVar1,is that correct?

当staticVar2可能更快时,statixVar1将始终被刷新.不保证何时,但订单有保证.

If thread A executes method,then later thread B executes method2(),is the value of staticVar2 published from A to B,even though the two threads don’t synchronize over the same lock?

是的,使用的锁对于先发生的保证无关紧要.

Do volatile read-writes flush all memory to all threads,or only between the two accessing threads? Whichever the answer,is all memory flushed or only the volatile variables?

所有脏内存都在写屏障上刷新,所有读取在读屏障上都是顺序一致的. volatile执行写操作时的写屏障和读操作时的读屏障.

Is all changed memory flushed when exiting a synchronized block,or just the memory that was changed within the block?

该线程改变了所有内存.

Do all static variables accessed by two threads have to be synchronized?

仅当一个线程修改变量时.任何数量的线程都可以读取静态值而无需同步.

原文地址:https://www.jb51.cc/java/128790.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐