Tag: java memory model

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

这个问题仅涉及内存可见性,不会发生在之前和发生之后。 Java中有四种方法可以保证一个线程中的内存更改对另一个线程可见。 (参考http://gee.cs.oswego.edu/dl/cpj/jmm.html ) 写入线程释放同步锁,读取线程随后获取相同的同步锁。 如果一个字段被声明为volatile,则在写入器线程执行任何进一步的内存操作之前,写入其中的任何值都会被写入器线程刷新并使其可见(即,出于手头的目的,它立即被刷新)。 线程第一次访问对象的字段时,它会看到字段的初始值或自某个其他线程写入的值。 当一个线程终止时,所有写入的变量都被刷新到主存储器。 根据Java Concurrency in Practice,关于这些问题的圣经: volatile变量的可见性效果超出了volatile变量本身的值。 当线程A写入易失性变量并且随后线程B读取相同的变量时,在读取volatile变量之后,在写入易失性变量之前A可见的所有变量的值变为可见。 挥发性的问题 这是否意味着JVM实际上跟踪了易失性变量读写,以便知道如何将内存从A刷新到B而不是A到C ? 所以A写入变量,后来C从变量读取,然后B从变量读取,刷新是在A和B以及A和C之间的每个线程基础上完成的,而不是 B和C ? 或者,它是否暗示所有缓存的内存都被刷新,无论线程如何? 只是刷新了volatile变量,还是所有缓存的内存? 同步问题 对于synchronized关键字刷新,它表示只有锁内部更新的内存才能保证发布到其他线程。 这意味着在下面的代码中,两个运行method()线程,保留synchronized块会将staticVar2刷新到另一个线程,但不是 staticVar1 ,这是正确的吗? 此外,在method2() ,如果另一个线程正在执行method()则可以导致在发生问题之前发生 – 遇到问题。 但是,问题在于可见性。 如果线程A执行method ,那么后来的线程B执行method2() ,是从A到B发布的staticVar2的值,即使这两个线程没有通过同一个锁同步? static int staticVar1, staticVar2; void method() { staticVar1++; synchronized (lock) { staticVar2++; } } void method2() { synchronized (differentLock) { […]

易失性读取是否发生在易失性写入之前?

我试着理解为什么这个例子是一个正确同步的程序: a – volatile Thread1: x=a Thread2: a=5 因为存在冲突的访问(存在对a的写入和读取)所以在每个顺序一致性执行中必须发生 – 在该访问之间的关系之前。 假设一个顺序执行: 1. x=a 2. a=5 1发生在2之前,为什么?

假设我知道我将在x64 cpu上运行,我可以忽略哪些JVM同步实践?

我知道JVM内存模型是为CPU的最小公分母而设计的,因此它必须假设JVM可以运行的最弱的cpu模型(例如ARM)。 现在,考虑到x64具有相当强大的内存模型,假设我知道我的程序只能在64位x86 CPU上运行,我可以忽略哪些同步实践? 当我的程序通过虚拟化运行时,这也适用吗? 例: 众所周知,JVM的内存模型需要同步对long和double的读/写访问,但可以假设其他32位原语(如int,float等)的读/写是primefaces的。 但是,如果我知道我在64位x86机器上运行,我是否可以忽略使用long / double上的锁定知道cpu将自动读取/写入64位值并保持它们不稳定(就像我对int / floats一样) )?

Java中“volatile”的含义是什么?

我们在其中一个项目中使用volatile来维护不同线程访问的变量的相同副本。 我的问题是使用volatile和static是否可以。 编译器没有给出任何错误,但我不明白使用两者的原因。

关于可见性及时性的易失性的详细语义

考虑一个volatile int sharedVar 。 我们知道JLS为我们提供了以下保证: 在写入操作happens-before ,在程序顺序中将写入值i到sharedVar happens-before的写入线程的每个动作happens-before ; 通过读取线程r从sharedVar成功读取i happens-before ,由w写入值i ; 读取线程r从sharedVar成功读取i happens-before在程序顺序中r所有后续动作happens-before 。 但是,对于读取线程何时观察到值i ,仍然没有挂钟时间保证。 一个完全不会让读取线程看到该值的实现仍然符合此契约。 我已经考虑了一段时间,我看不到任何漏洞,但我认为必须有。 请指出我的推理漏洞。

Java并发:是最终字段(在构造函数中初始化)是线程安全的吗?

谁能告诉我这个类是否是线程安全的? class Foo { private final Map aMap; public Foo() { aMap = new HashMap(); aMap.put(“1”, “a”); aMap.put(“2”, “b”); aMap.put(“3”, “c”); } public String get(String key) { return aMap.get(key); } } 编辑:我不能澄清这个问题。 根据JMM FAQ : 应提供初始化安全性的新保证。 如果正确构造了一个对象(这意味着对它的引用在构造期间不会被转义),那么看到对该对象的引用的所有线程也将看到在构造函数中设置的最终字段的值,而不需要同步。 这让我感到困惑的是,set到aMap是aMap = new HashMap(); 。 所以其他线程可以看到这些 aMap.put(“1”, “a”); aMap.put(“2”, “b”); aMap.put(“3”, “c”); 或不 ? 编辑:我发现这个问题与我的问题完全不同