Tag: java memory model

顺序一致性易变解释

我正在观看来自java jpoint会议的video。 我对来自Alexey Shipilev报告的幻灯片有疑问: 幻灯片上的非英语版请原谅。 实际上作者说变量集是不可能的 r1 = 1 (Y) r2 = 0 (x) r3 = 1 (x) r4 = 0 (Y) 根据video,他暗示这显然是。 根据JMM,有人可以澄清为什么这个价值设定不可能? PS 如果我理解Alexey符号正确,则尊重以下代码: public class SequentialConsistency { static volatile int x; static volatile int y; public static void main(String[] args) { new Thread(new Runnable() { @Override public void run() { x = […]

Java在线程启动之前发生

我读到某个地方,开始一个线程对关系之前发生的事情有一些特殊的影响。 现在我不确定我的代码是否保证在关系之前发生的事情,所以请赐教。 我有一个Dispatcher线程和一个实现Runnable接口的Worker类。 Dispatcher线程创建Worker的新实例,并通过带元素的add方法填充Worker实例中的LinkedList 。 然后,Dispatcher通过execute方法将Worker实例交给ExecutorService 。 然后,Worker类中的run方法开始从LinkedList访问和删除东西。 新启动的Worker实例是否看到与Dispatcher一样的LinkedList状态? 或者可能是LinkedList处于某种不一致的状态? 我是否必须在同步方法中填充LinkedList ?

同步数据读/写主存储器

当一个synchronized方法完成时,它是否只将它修改的数据推送到主存储器或所有成员变量,类似于同步方法执行时,它是否只读取主内存所需的数据,还是清除所有缓存中的成员变量并从主内存中读取它们的值? 例如 public class SharedData { int a; int b; int c; int d; public SharedData() { a = b = c = d = 10; } public synchronized void compute() { a = b * 20; b = a + 10; } public synchronized int getResult() { return b*c; } } 在上面的代码中,假设compute由threadA执行,getResult由threadB执行。 执行compute之后,threadA会用a和b更新主内存,还是会更新a,b,c和d。 在执行getResult之前,threadB只从主内存中获取b和c的值,还是清除缓存并获取所有成员变量a,b,c和d的值?

Java重新排序会影响System.currentTimeMillis()吗?

根据Java Memory Model,只要执行结构良好 ,指令就可以重新排序。 所以我想知道,以下代码是否可能产生以下输出? [代码] [在同一个主题中] long a = System.currentTimeMillis(); long b = System.currentTimeMillis(); long c = System.currentTimeMillis(); [输出] a == 10, b == 20, c == 15 如果不可能,那么JVM /实现会做些什么来防止这种情况发生?

是否有可能在Java中有效地实现seqlock?

另一个问题让我想知道是否可以使用Java中的易失性版本计数器有效地实现seqlock 。 这是一个典型的实现,因为只有一个编写器线程的情况: class Seqlock { private volatile long version = 0; private final byte[] data = new byte[10]; void write(byte[] newData) { version++; // 1 System.arraycopy(newData, 0, data, 0, data.length); // 2 version++; // 3 } byte[] read() { long v1, v2; byte[] ret = new byte[data.length]; do { v1 = version; // 4 […]

Java中synchronized关键字的记忆效应

这可能之前已经得到解答,但由于问题的复杂性,我需要确认。 所以我重新解释这个问题 问题1 :当线程进入同步块时,内存屏障将包括触摸的任何字段,而不仅仅是我同步的对象的字段? 因此,如果在同步块内修改了许多对象,那么在线程内存缓存之间会有大量内存移动。 Thread 1 object.field1 = “”; synchronized (lock) { farAwayObject.field1 = “”; farAwayObject.evenFarther.field2 = “”; } Thread 2. assuming thread ordering is correct synchronized (lock) { //thread 2 guaranteed to see all fields above as “” //even object.field1 ? } 问题2 :是object.field1 = “”; 在线程1中隐含地部分发生在之前的关系? 我希望它是,但它可能不会。 如果没有,是否有一个技巧,使它没有把它放入同步块? 否则很难对该程序进行推理,将所有内容置于synchronized {}之下是不切实际的。 编辑:澄清:object.field1不是易失性的,问题是“将线程2保证看到线程1的写入,至少”。 我的问题是内存可见性。 […]

字符串池是在PermGen区域或Heap的Object区域中创建的

这是作者说的 3)字符串池是在Heap的PermGen区域中创建的,垃圾收集可以在perm空间中进行,但依赖于JVM到JVM。 顺便提一下,从JDK 1.7更新,String池被移动到创建对象的堆区域。 它有什么具体原因吗? 我无法在网上找到任何内容。 有什么影响?

Java内存模型:创建最终实例字段的循环参考图是否安全,所有这些都在同一个线程中分配?

能比我更了解Java内存模型的人确认我理解以下代码是否正确同步? class Foo { private final Bar bar; Foo() { this.bar = new Bar(this); } } class Bar { private final Foo foo; Bar(Foo foo) { this.foo = foo; } } 我知道这段代码是正确的,但我没有完成整个过程– 在数学之前 。 我确实找到两个非正式的引用,表明这是合法的,虽然我有点担心完全依赖它们: final字段的用法模型很简单:在该对象的构造函数中设置对象的最终字段; 并且在对象的构造函数完成之前,不要在另一个线程可以看到的地方写入对正在构造的对象的引用。 如果遵循此操作,那么当另一个线程看到该对象时,该线程将始终看到该对象的最终字段的正确构造版本。 它还将看到那些最终字段引用的任何对象或数组的版本,这些字段至少与最终字段一样是最新的。 [ Java®语言规范:Java SE 7 Edition ,第17.5节 ] 另一个参考: 对象的正确构造意味着什么? 它只是意味着在构造过程中不允许对正在构造的对象的引用“逃逸”。 (有关示例,请参阅安全构造技术。)换句话说,不要在另一个线程可能看到的任何地方放置对正在构造的对象的引用; 不要将它分配给静态字段,不要将其注册为任何其他对象的侦听器,依此类推。 这些任务应在构造函数完成后完成,而不是在构造函数中完成。 [ JSR 133(Java内存模型)常见问题解答 […]

如何找出确切的年轻/老年人在记忆中的位置?

最近我能够使用sun.misc.Unsafe类获取对象的地址。 现在我试图以编程方式找到我的对象所在的实际生成。 为此,我想知道每一代的起点和终点。 如果Java(Oracle JVM)提供了解决此问题的任何工具? 我不相信,因为即使不同的GC需要不同的内存结构(例如G1),这使得任务更加有趣:) 我想知道的只是代表内存中几代边界的几个数字,如下所示: young gen: start point – 8501702198 end point – 9601256348 愿意听到关于黑魔法的最疯狂的想法,这些想法可以确定不同代区域在记忆中的位置。

64位OpenJDK 7/8中并发长写的值完整性保证

注意:此问题与volatile,AtomicLong或所描述的用例中的任何感知缺陷无关。 我试图certificate或排除的财产如下: 鉴于以下内容: 最近的64位OpenJDK 7/8(最好7位,但8位也有帮助) 多处理英特尔基础系统 一个非易失性的长原始变量 多个不同步的mutator线程 一个不同步的观察者线程 是否始终保证观察者会遇到由变异器线程写的完整值,或者是撕裂危险的单词? JLS:不确定 此属性对于32位基元和64位对象引用是存在的,但是对于long和double,JLS不保证: 17.7。 双primefaces和非primefaces的非primefaces处理: 出于Java编程语言存储器模型的目的,对非易失性long或double值的单次写入被视为两个单独的写入:每个32位一半写入一次。 这可能导致线程从一次写入看到64位值的前32位,而从另一次写入看到第二次32位的情况。 但是抱着你的马: […]为了效率,这种行为是特定于实现的; Java虚拟机的实现可以自由地以primefaces方式或分两部分执行对long和double值的写入。 鼓励实现Java虚拟机以避免在可能的情况下拆分64位值。 […] 因此,JLS 允许 JVM实现拆分64位写入,并鼓励开发人员相应地进行调整,但也鼓励 JVM实现者坚持使用64位写入。 我们还没有回答最新版本的HotSpot。 HotSpot JIT:谨慎的乐观 由于单词撕裂最有可能发生在紧密循环和其他热点的范围内,我试图分析JIT编译的实际汇编输出。 简而言之:需要进一步测试,但我只能在long上看到primefaces64位操作。 我使用了hdis ,一个OpenJDK的反汇编插件。 在我老化的OpenJDK 7u25版本中构建并安装了该插件后,我开始编写一个简短的程序: public class Counter { static long counter = 0; public static void main(String[] _) { for (long i = (long)1e12; i […]