问题

我的老师在一个关于线程的上层java课上说了一些我不确定的东西。

他表示以下代码不一定会更新2910104598变量。根据他的说法,两个线程不一定共享静态变量,特别是在每个线程(主线程与ReaderThread)在其自己的处理器上运行并因此不共享相同的寄存器/缓存/等的情况下CPU不会更新另一个。

基本上,他说有可能ready在主线程中更新,但不在ReaderThread中更新,因此ReaderThread将无限循环。他还声称该程序可以打印'0'或'42'。我知道如何打印'42',但不能打印'0'。他提到当number变量设置为默认值时会出现这种情况。

我想也许不能保证在线程之间更新静态变量,但这对我来说非常奇怪。 makereadyvolatile正确吗?

他展示了这段代码:

public class NoVisibility {

private static boolean ready;

private static int number;

private static class ReaderThread extends Thread {

public void run() {

while (!ready) Thread.yield();

System.out.println(number);

}

}

public static void main(String[] args) {

new ReaderThread().start();

number = 42;

ready = true;

}

}

#1 热门回答(59 赞)

静态变量没有特定的可见性问题。 JVM的内存模型强调了可见性问题.Here's an article talking about the memory model and how writes become visible to threads。你不能指望一个线程及时变得对其他线程可见的更改(实际上JVM没有义务让这些更改完全可见),除非你建立ahappens-before relationship,这里是该链接的引用(提供)在Jed Wesley-Smith的评论中):

Java语言规范的第17章定义了内存操作的先发生关系,例如共享变量的读写。只有在读取操作之前发生写入操作时,一个线程的写入结果才能保证对另一个线程的读取可见。 synchronized和volatile构造以及Thread.start()和Thread.join()方法可以形成先发生关系。特别是:线程中的每个动作都发生在该线程中的每个动作之前,该动作在程序的顺序中稍后出现。监视器的解锁(同步块或方法退出)发生在同一监视器的每个后续锁定(同步块或方法入口)之前。并且因为发生在之前的关系是可传递的,所以在解锁之前线程的所有动作都发生在任何线程锁定该监视器之后的所有动作之前。对易失性字段的写入发生在每次后续读取该相同字段之前。易失性字段的写入和读取具有与进入和退出监视器类似的内存一致性效果,但不需要互斥锁定。在启动线程中的任何操作之前发生对线程启动的调用。线程中的所有操作都发生在任何其他线程从该线程上的连接成功返回之前。

#2 热门回答(28 赞)

他在谈论可见性而不是太过于字面意思。

静态变量确实在线程之间共享,但是在一个线程中进行的更改可能不会立即对另一个线程可见,使得看起来有两个变量副本。

本文提供了一个与他如何呈现信息一致的视图:

http://jeremymanson.blogspot.com/2008/11/what-volatile-means-in-java.html

首先,你必须了解Java内存模型的一些内容。多年来我一直在努力解释一下这个问题。截至今天,我能想到的最好的方式是描述它:如果你用这种方式想象它:Java中的每个线程都发生在一个单独的存储空间中(这显然是不真实的,所以请耐心等待这一点)。你需要使用特殊机制来保证在这些线程之间进行通信,就像在消息传递系统上一样。在一个线程中发生的内存写入可以"泄漏"并被另一个线程看到,但这绝不是保证。如果没有明确的通信,你无法保证其他线程可以看到哪些写入,甚至无法保证看到它们的顺序。 ...

但同样,这只是思考线程和易失性的心理模型,而不是字面上JVM的工作方式。

#3 热门回答(9 赞)

基本上它是真的,但实际上问题更复杂。共享数据的可见性不仅会受到CPU缓存的影响,还会受到指令的无序执行的影响。

因此,Java定义了aMemory Model,它指出线程在哪种情况下可以看到共享数据的一致状态。

在你的特定情况下,添加volatile保证可见性。

java 线程 静态变量_线程之间是否共享静态变量?相关推荐

  1. jmeter进程和线程的区别_接口测试01- Jmeter-线程进程-环境变量

    1.1 概念 JMeter 是 Apache 组织使用 Java 开发的一款测试工具 ,它最初被设计用于Web应用测试,但后来扩展到其他测试领域. 它可以用于测试静态和动态资源,例如静态文件.Java ...

  2. java同步锁售票_线程同步锁之火车站售票案例

    前言: 谈到多线程,就不得不说线程同步,那么什么是线程同步? 线程同步 即当有一个线程在对内存进行操作时,其他线程都不可以对这个内存地址进行操作,直到该线程完成操作, 其他线程才能对该内存地址进行操作 ...

  3. java 信号量 互斥锁_线程同步(互斥锁与信号量的作用与区别)

    "信号量用在多线程多任务同步的,一个线程完成了某一个动作就通过信号量告诉别的线程,别的线程再进行某些动作(大家都在semtake的时候,就阻塞在 哪里).而互斥锁是用在多线程多任务互斥的,一 ...

  4. java 线程亲缘性_线程的调度、优先级和亲缘性

    每隔20ms左右,Windows要查看当前存在的所有线程内核对象.在这些对象中,只有某些对象被视为可以调度的对象.Windows选择可调度的线程内核对象中的一个,将它加载到CPU的寄存器中,它的值是上 ...

  5. java线程池大小_线程池大小设置多少合适?java如何合理设置线程池大小?

    在连接数据库时我们经常会用到线程池,而有时候我们就会烦恼,线程池的大小究竟该设置成多大才合适呢?小伙伴们知道要如何合理设置线程池大小吗?下面跟小编一起来看看吧. 一般来说,我们线程池究竟设置多大是基于 ...

  6. java executors 详解_线程池—Executors 详解

    各位志同道合的朋友们大家好,我是一个一直在一线互联网踩坑十余年的编码爱好者,现在将我们的各种经验以及架构实战分享出来,如果大家喜欢,就关注我,一起将技术学深学透,我会每一篇分享结束都会预告下一专题 线 ...

  7. java executors 详解_线程池Executors详解

    为什么要用线程池呢? 一是减少了创建和销毁线程的次数,每个工作线程都可以被重复利用,可执行多个任务; 二是可以根据系统的承受能力,调整线程池中工作线线程的数目,防止因为因为消耗过多的内存,而把服务器累 ...

  8. 线程基础知识_线程生命周期_从JVM内存结构看多线程下的共享资源

    线程生命周期 线程状态 New: 线程创建(new Thread()) Runnable: 线程可运行(thread.start()), 注: 调用start并不一定是运行状态, 可能在等待CPU调度 ...

  9. 如何保证线程安全有序性_线程安全性-原子性-可见性-有序性

    一.相关定义: 线程安全类:当多个线程访问某个类时,不管运行环境采用何种调度方式或者这些进程如何交替执行,并且在主调代码中不需要任何额外的同步或协同,这个类都能表现出正确的行为,那么就称这个类是线程安 ...

最新文章

  1. Android--SQLite(一)
  2. 使用神经网络提取PDF表格工具来了,支持图片,关键是能白嫖谷歌GPU资源
  3. 关于IOS给我的启发
  4. Meet new Sentinel Go committers!
  5. Flutter 制作漂亮的登录表单
  6. 一年带货2个亿,“小黄鸭”成国内最赚钱IP
  7. 不再“挤牙膏”!英特尔公布技术路线图,豪迈放言:“将在 2025 年夺回芯片性能桂冠!”...
  8. [Python] zeros(r, c)和ones(r, c)和eye(n) 生成特殊矩阵
  9. java8日期加减_JDK 8 三种时间获取方法 日期加减
  10. cpu占用突然到百分百又降下去_cpu使用率忽高忽低
  11. matlab 二值图像黑白颠倒,白天不懂夜的黑,为你开启PS黑白颠倒魔法。
  12. 网易云音乐评论爬虫 params encSecKey逆向分析!
  13. 从 Google Play 下载 APK 文件
  14. html 斜体变正体怎么变,WORD中编辑公式时怎样将斜体改成正体
  15. 【chrome】Chrome源码剖析、上--多线程模型、进程通信、进程模型
  16. 1646. Prime Path
  17. 单片机应用程序开发QY-JXSY51
  18. 全面了解三极管——三极管基本参数1
  19. 2022继电保护判断题及答案
  20. 程序员需要研究厚黑学吗

热门文章

  1. python判断输入的字符串是否是回文联
  2. linux双显卡开机界面,红帽linux系统nvidia显卡启动
  3. python发微信语音没声音怎么回事_我的微信发语音没声音怎么回事
  4. win下bat批量重命名文件
  5. WPF XAML X名称空间详解
  6. java实现正态分布(钟形曲线)
  7. 安卓活体检测的源码支持(摇头点头微笑眨眼检测)
  8. 一些 刊号期号计算方式
  9. 汉字编码与编程相关问题总结:ASCII、机内码、区位码、国标码、Unicode码他们之间是如何转换的
  10. A*:python实现A星寻路算法可视化