Tag: 内存模型

什么是“顺序一致的执行没有数据竞争”?

在JLS中,§17.4.5。 发生在秩序之前 ,它说 当且仅当所有顺序一致的执行没有数据争用时,程序才能正确同步。 它只给我们定义“顺序一致”,它没有给我们定义“顺序一致的执行”。 只有在知道什么是“顺序一致的执行”之后,我们才可以进一步讨论该主题。 什么是“顺序一致的执行”以及什么是“顺序一致的执行没有数据竞争”?

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内存模型)常见问题解答 […]

使用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) { […]

empty synchronized(this){}对线程之间的内存可见性有什么意义吗?

我在StackOverflow的评论中读到了这个: 但是如果你想要安全,你可以在@PostConstruct [方法]的末尾添加简单的synchronized(this){} [注意变量不易变化] 我认为只有在synchronized块中执行写入和读取或者至少读取是易失性时才强制执行before-before 。 引用的句子是否正确? 空的synchronized(this) {}块是否将当前方法中更改的所有变量刷新为“一般可见”内存? 请考虑一些场景 如果第二个线程永远不会锁定this怎么办? (假设第二个线程读入其他方法)。 请记住,问题是: 刷新对其他线程的更改 ,而不是给其他线程一种方式(同步)来轮询原始线程所做的更改 。 在Spring @PostConstruct上下文中,很可能在其他方法中没有同步 – 正如原始评论所说。 是仅在另一个线程的第二次和后续调用中强制执行的更改的内存可见性? (请记住,这个同步块是我们方法中的最后一次调用) – 这会将这种同步方式标记为非常糟糕的做法(第一次调用中的陈旧值)

Java中的Peterson算法?

在Java中是否存在用于互斥的Peterson算法的示例实现?

如何理解发生 – 在一致之前

在JLS的第17章中 ,它引入了一个概念:在一致之前发生。 如果对于A中的所有读取r,其中W(r)是r看到的写入动作,那么一组动作A发生 – 在一致之前,不是hb(r,W(r))或那里的情况在A中存在写w,使得wv = rv和hb(W(r),w)和hb(w,r)“ 在我的理解中,它等于以下几个词:……,既不是……也不是…… 所以我的前两个问题是: 我的理解对吗? “wv = rv”是什么意思? 它还给出了一个例子:17.4.5-1 Thread 1 Thread 2 B = 1; A = 2; r2 = A; r1 = B; 在第一个执行顺序中: 1: B = 1; 3: A = 2; 2: r2 = A; // sees initial write of 0 4: r1 = B; // sees […]