如果从多个线程访问Java中的变量,则必须确保安全发布它们。这通常意味着使用synchronized
或volatile
。
我的印象是,我的一些同事没有认真对待这个问题,因为他们“从未听说volatile
过,他们的程序已经工作了很多年”。
所以我的问题是:
有人可以提供一个示例Java程序/片段来可靠地显示数据可见性问题。
我认为运行程序并看到意外的NPE或过时的变量值会比理论上的解释更有帮助,这是无法证明的。
非常感谢你的帮助!
更新: 只是再次强调这一点。我已经阅读了 Java Concurreny in Practice, 并了解了 理论上
存在可见性问题的示例。我正在寻找的是一种实际 演示 它们的方法。我不确定这是否确实可行,但是也许有jvm配置或类似的配置允许它。
通过删除操作修改此处的示例,我得出一个示例
提出强调使用volatile重要性的最常见示例是while(keepRunning):
public class Test extends Thread {
boolean keepRunning = true;
public static void main(String[] args) throws InterruptedException {
Test t = new Test();
t.start();
Thread.sleep(1000);
t.keepRunning = false;
System.out.println(System.currentTimeMillis() + ": keepRunning is false");
}
public void run() {
while (keepRunning)
System.out.println(System.currentTimeMillis() + ": " + keepRunning);
}
}
由于keepRunning
可以(有效地)保留在运行while
循环的线程的高速缓存中,因此在将程序设置为false keepRunning
后,该程序可能会长时间打印“ true” keepRunning
。
但是请注意,没有公开竞争条件的可靠方法。(请参阅我的其他答案。)在某些情况下,此示例可能在硬件/操作系统/ jvm的某些组合中公开。
该示例在我的环境中始终失败(线程永不停止运行)。
// Java environment:
// java version "1.6.0_0"
// OpenJDK Runtime Environment (IcedTea6 1.6.1) (6b16-1.6.1-3ubuntu3)
// OpenJDK 64-Bit Server VM (build 14.0-b16, mixed mode)
public class Test2 extends Thread {
boolean keepRunning = true;
public static void main(String[] args) throws InterruptedException {
Test2 t = new Test2();
t.start();
Thread.sleep(1000);
t.keepRunning = false;
System.out.println(System.currentTimeMillis() + ": keepRunning is false");
}
public void run() {
while (keepRunning)
{}
}
}
注意,这类问题完全取决于编译器/运行时/系统。特别是,编译器可以确定添加指令以从内存中读取变量,即使它不是易失性的(这样代码也可以工作),因此vm和jit可以优化从内存中的读取操作,仅使用寄存器,甚至可以使用寄存器。处理器可以对指令重新排序-
不会影响这种情况,但是在其他多线程情况下,如果修改了多个变量,它可能会影响其他线程的感知状态。
我正在学习Java的易失性,我的代码是这样的。 我知道如果flag没有volatile,线程就不会存在。这是能见度的问题。 但是,如果我在while循环中编写一些代码,如,t1线程将读取新值并停止循环。 我知道如何使用volatile来解决可见性问题,所以我的问题是: 为什么当我写?
问题内容: 当我阅读“ 实践中的Java并发性 ” c03时,我对以下程序感到困惑: 由于重新排序和线程可见性,循环可能永远不会停止,或者输出可能为零,但是我已经尝试了很多次,并且输出始终为42。所有原因是我太幸运了吗? 问题答案: 所有的原因是我太幸运了吗? 不必要。这也将取决于您的处理器体系结构和JVM实现。那就是微妙的内存模型问题的问题之一:它们很难在野外复制。
1):单线程应用程序只会在用户的CPU上使用1个线程吗?提供更多的线程会使用多个CPU内核吗?如果声明的线程比用户的CPU多,会发生什么?
Workerman有一个依赖pthreads扩展的MT多线程版本,但是由于pthreads扩展还不够稳定,所以这个Workerman多线程版本已经不再维护。 目前Workerman及其周边产品都是基于多进程单线程的。
如图所示, 位置 2 和位置3 为什么可以访问 位置1 (也就是主线程)的 point 局部变量 ? 毕竟 位置 2 和位置3 是另外两个线程啊 !! 当我加上 第10行代码后,thread1 和 thead2 中都不能访问主线程中的point 了。我知道这是内部类的“事实最终变量” 的限制。 如下图所示,就是我不理解的地方。(在 “栈内存” 层面) 我的猜测:之所以 thread1 和 trea
全球销量第一的表格控件,类似Excel的强大功能 Spread for ASP.NET表格控件兼容Excel的强大功能,并将其嵌入到您的应用系统中。完备的Excel文档支持使得您可以在企业中分享和访问数据信息;内嵌的图表引擎和数据可视化支持让您更加轻松的为商务、工程以及科学应用系统中创建丰富高效的信息中心。