Tag: 易失性

使用java的multithreading概念控制运行Thread

我只想在按下返回键时启动并停止线程。 这里线程停止正常,但我不能再次启动该线程请帮助。 还解释了我使用volatile关键字。这对我来说是有帮助的。 public class Sync extends Thread{ public boolean meth= true; public void run(){ while(meth){ System.out.println(“hello”); try { Thread.sleep(1000); } catch (InterruptedException ex) { } } } public void shutdown(){ meth=false; } public void startup(){ meth=true; } } 主类“ package com.Sync; import java.util.Scanner; public class SyncMain { public static void main(String[] arg) throws InterruptedException{ […]

如何使volatile count操作成为线程安全的

我一直在经历JCIP,作者在那里说.. 线程限制的一个特例适用于volatile变量。 只要确保volatile变量仅从单个线程写入,对共享的volatile变量执行读 – 修改 – 写操作是安全的。 例如,count ++被认为是一个复合操作(读取值,添加一个值,并更新值)并将count指定为volatile不会使此操作成为primefaces,因此这里不保证线程安全! 我对吗 ?? 但是这里作者说我们可以修复它,如果我们确保volatile变量只是从一个线程写的。 我没理解这一点。 请提供说明。

理解记忆障碍

我试图在一个对java无锁程序员有用的级别上理解内存障碍。我觉得这个级别介于学习挥发性和从x86手册学习存储/加载缓冲区的工作之间。 我花了一些时间阅读一堆博客/烹饪书,并提出了以下摘要。 有更多知识渊博的人可以查看摘要,看看我是否遗漏了错误或列出的内容。 LFENCE: Name : LFENCE/Load Barrier/Acquire Fence Barriers : LoadLoad + LoadStore Details : Given sequence {Load1, LFENCE, Load2, Store1}, the barrier ensures that Load1 can’t be moved south and Load2 and Store1 can’t be moved north of the barrier. Note that Load2 and Store1 can still be reordered. Buffer Effect : Causes […]

线程安全无波动

谁能解释为什么这个例子是没有volatile的线程安全的? http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html 实际上,假设computeHashCode函数总是返回相同的结果并且没有副作用(即幂等),您甚至可以摆脱所有同步。 // Lazy initialization 32-bit primitives // Thread-safe if computeHashCode is idempotent class Foo { private int cachedHashCode = 0; public int hashCode() { int h = cachedHashCode; if (h == 0) { h = computeHashCode(); cachedHashCode = h; } return h; } // other functions and members… } 更多:我明白了,我们不关心值是否计算两次(因此它不是真正的线程安全)。 我还想知道在计算哈希码之后创建的新线程是否可以保证看到新的哈希码?

java中的volatile变量和内存障碍

我有一个由链接节点组成的数据结构。 您可以将其视为简单的LinkedList。 列表的每个节点由一些值和指向另一个节点的下一个字段组成,如果它是最后一个节点则为null。 第一个节点作为根,它没有值,只指向下一个节点。 所有其他节点实际上是不可变的,一旦它们被创建,它们的值和它们的下一个字段在生命期间都不会改变,除非正在处理与特定情况有关的结构。 一个(仅一个)线程将新节点添加到列表的前面。 它是通过构造一个新对象,设置其字段并将下一个字段设置为根指向的对象,然后将根的下一个字段设置为此新节点来实现的。 其他节点浏览仅执行读取的结构。 它们具有对根节点的引用,然后它们通过其他节点,直到它们找到正在查找的内容或到达列表的末尾。 我的问题是:是否足以让下一个字段变得易变? 根据我对java内存模型的理解,如果主线程(添加新节点的线程)在添加新节点时将执行易失性写入,那么一切都将很好地同步,并且不会发生任何不一致。 也是正确的假设在x86架构上读取volatile变量不会导致任何性能下降? 由于其他线程经常浏览读取下一个字段的结构,因此可以自由地完成此操作而不需要任何内存屏障等。 我还有一个问题。 要浏览结构的线程也将保留一些额外的节点。 这些节点将完全是线程本地的,它们将仅由创建它们的线程使用,并且根本不会被共享。 对于这些附加节点,下一个字段不必是易失性的。 此外,设置易失性下一字段将发出存储器屏障,这将导致不期望的性能损失。 我想知道有没有办法避免这种情况。 理想情况下,如果下一个字段有时会作为一个易失性字段而有时作为一个普通字段工作,那将是完美的;)或者如果我有完全控制并且可以在我需要的时候自行发出内存屏障。 编辑: 我也想知道是否有可能以不同的方式在不同的volatile变量上同步所有这些写入? 例如一些其他完全不相关的静态变量? 由于volatile写入刷新所有挂起的写入,下一个字段是不是可能不是易失性的,而是在更新线程完成所有工作后会写入不同的volatile变量? 它对我来说看起来不太安全,因为在关系之前没有发生,之前的写入可能会被重新排序。 可以使用值字段分配重新下载下一个字段分配,从而导致迭代线程观察到不一致的对象状态。 但也许有可能提出这样一个安全的方案吗? 这个怎么样: 更新线程首先构造一个新对象,初始化其值字段,将其下一个字段设置为根节点指向的节点, 对某个静态变量执行易失性写入 ,将根节点的下一个字段设置为新创建的节点

易失性:为什么要阻止编译器重新排序代码

在java中,据我所知,volatile变量使线程直接读/写到主CPU(而不是每个线程的缓存中),因此将其更改显示给其他线程。 我不知道的是:那么,为什么这个工作(volatile)可以阻止编译器/ CPU重新排序代码语句。 谢谢 :)

为什么Java中的volatile不会更新变量的值?

我已经读过Java中的“volatile”允许不同的线程访问同一个字段并查看其他线程对该字段所做的更改。 如果是这种情况,我预测当第一个和第二个线程完全运行时,“d”的值将增加到4.但是,每个线程将“d”增加到值2。 public class VolatileExample extends Thread { private int countDown = 2; private volatile int d = 0; public VolatileExample(String name) { super(name); start(); } public String toString() { return super.getName() + “: countDown ” + countDown; } public void run() { while(true) { d = d + 1; System.out.println(this + “. Value of […]

Java文档中的易失性变量说明

当线程读取volatile变量时,它不仅会看到volatile的最新更改,还会看到导致更改的代码的副作用 这在http://docs.oracle.com/javase/tutorial/essential/concurrency/atomic.html中提到 有人可以提供一个例子吗? 这首先给我的印象是,读取volatile变量的线程将与writer线程同步并等待写入完成。 但事实显然并非如此。 一个例子可以帮助很多,非常感激。 谢谢,穆斯塔法

说明volatile:这个代码是线程安全的吗?

我试图用一个例子来说明volatile的用法和重要性,如果省略volatile ,那么这个例子真的不会给出好的结果。 但我并不习惯使用volatile 。 如果省略volatile ,则以下代码的想法是导致无限循环,如果存在volatile则完全是线程安全的。 以下代码是否是线程安全的? 你有没有其他现实和简短的使用volatile的代码示例,没有它会给出明显不正确的结果吗? 这是代码: public class VolatileTest implements Runnable { private int count; private volatile boolean stopped; @Override public void run() { while (!stopped) { count++; } System.out.println(“Count 1 = ” + count); } public void stopCounting() { stopped = true; } public int getCount() { if (!stopped) { throw […]

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

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