java 并发线程

当在不同线程之间共享对象的状态时,除了原子性外,其他问题也会发挥作用。 其中之一是可见性。

关键事实是,如果没有同步,则不能保证指令按照它们在源代码中出现的顺序执行。 这不会影响单线程程序中的结果,但是,在多线程程序中,如果一个线程更新值,则另一个线程可能在需要或不看到更新时看不到更新一切。

在多线程环境中,程序有责任确定何时在不同线程之间共享数据并采取相应措施(使用同步)。

NoVisibility中的示例包含两个共享标志的线程。 写入器线程更新标志,而读取器线程等待直到设置了标志:

public class NoVisibility {private static boolean ready;public static void main(String[] args) throws InterruptedException {new Thread(new Runnable() {@Overridepublic void run() {while (true) {if (ready) {System.out.println("Reader Thread - Flag change received. Finishing thread.");break;}}}}).start();Thread.sleep(3000);System.out.println("Writer thread - Changing flag...");ready = true;}
}

该程序可能会导致无限循环,因为读取器线程可能看不到更新的标志并永远等待。

通过同步,我们可以确保不会发生这种重新排序,从而避免了无限循环。 为了确保可见性,我们有两种选择:

  • 锁定:保证可见性和原子性(只要使用相同的锁定)。
  • 易挥发的字段:保证可见性。

volatile关键字的作用类似于某种同步块。 每次访问该字段时,就像输入同步块一样。 主要区别在于它不使用锁。 因此,它可能适用于上述示例(更新共享标志),但不适用于复合操作。

现在,我们将volatile关键字添加到ready字段,以修改前面的示例。

public class Visibility {private static volatile boolean ready;public static void main(String[] args) throws InterruptedException {new Thread(new Runnable() {@Overridepublic void run() {while (true) {if (ready) {System.out.println("Reader Thread - Flag change received. Finishing thread.");break;}}}}).start();Thread.sleep(3000);System.out.println("Writer thread - Changing flag...");ready = true;}
}

可见性将不再导致无限循环。 作者线程进行的更新将对读者线程可见:

Writer thread - Changing flag...

读取器线程-收到标志更改。 精加工螺纹。

结论

我们了解了在多线程程序中共享数据时的另一种风险。 对于一个简单的示例(如此处所示),我们可以简单地使用一个volatile字段。 其他情况将要求我们使用原子变量或锁定。

  • 您可以在github上查看源代码。

翻译自: https://www.javacodegeeks.com/2014/08/java-concurrency-tutorial-visibility-between-threads.html

java 并发线程

java 并发线程_Java并发教程–线程之间的可见性相关推荐

  1. java 关闭守护线程_Java并发编程之线程生命周期、守护线程、优先级、关闭和join、sleep、yield、interrupt...

    Java并发编程中,其中一个难点是对线程生命周期的理解,和多种线程控制方法.线程沟通方法的灵活运用.这些方法和概念之间彼此联系紧密,共同构成了Java并发编程基石之一. Java线程的生命周期 Jav ...

  2. java 多线程 任务队列_Java并发编程线程池任务队列

    类ThreadPoolExecutor最常使用的构造方法是: ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliv ...

  3. java 并发锁_Java并发教程–锁定:内在锁

    java 并发锁 在之前的文章中,我们回顾了在不同线程之间共享数据的一些主要风险(例如原子性和可见性 )以及如何设计类以安全地共享( 线程安全的设计 ). 但是,在许多情况下,我们将需要共享可变数据, ...

  4. java并发调用_Java并发教程–可调用,将来

    java并发调用 从Java的第一个发行版开始,Java的美丽之处之一就是我们可以轻松编写多线程程序并将异步处理引入我们的设计中. Thread类和Runnable接口与Java的内存管理模型结合在一 ...

  5. java并发队列_Java并发教程–阻塞队列

    java并发队列 如第3部分所述,Java 1.5中引入的线程池提供了核心支持,该支持很快成为许多Java开发人员的最爱. 在内部,这些实现巧妙地利用了Java 1.5中引入的另一种并发功能-阻塞队列 ...

  6. java 并发锁_Java并发教程–重入锁

    java 并发锁 Java的synced关键字是一个很棒的工具–它使我们可以通过一种简单可靠的方式来同步对关键部分的访问,而且也不难理解. 但是有时我们需要对同步进行更多控制. 我们要么需要分别控制访 ...

  7. java线程池教程_Java基础教程——线程池

    启动新线程,需要和操作系统进行交互,成本比较高. 使用线程池可以提高性能-- 线程池会提前创建大量的空闲线程,随时待命执行线程任务.在执行完了一个任务之后,线程会回到空闲状态,等待执行下一个任务.(这 ...

  8. java 进程描述_java 进程和线程

    什么是进程,什么是线程? 进程:是并发执行的程序在执行过程中分配和管理资源的基本单位,是一个动态概念,竞争计算机系统资源的基本单位. 线程:是进程的一个执行单元,是进程内科调度实体.比进程更小的独立运 ...

  9. java计算时间差_JAVA并发编程三大Bug源头(可见性、原子性、有序性),彻底弄懂...

    原创声明:本文转载自公众号[胖滚猪学编程]​ 某日,胖滚猪写的代码导致了一个生产bug,奋战到凌晨三点依旧没有解决问题.胖滚熊一看,只用了一个volatile就解决了.并告知胖滚猪,这是并发编程导致的 ...

最新文章

  1. android 开发时遇到的各种问题1--Android双模(CDMA/GSM)手机短信相关
  2. MySQL 架构组成—存储引擎
  3. Struts的基础案例的步骤
  4. HDU 1247(Hat’s Words )
  5. pytorch入门使用
  6. js 获取url问号前_收下这波 JS 技巧,从此少加班
  7. 在react里写原生js_从零开始使用react+antd搭建项目
  8. 程序员1年经验包装成5年,转正时领导:试用期不想过了?
  9. 初识Memcache之安装与测试
  10. 小孩桌面便签隐藏了怎么恢复?
  11. Linux中fork函数详解(附图解与代码实现)
  12. 一个简单的鼠标钩子程序
  13. 使用pdfobject.js实现在线浏览PDF--后台上传保存文件
  14. [UE4]IsValid方法妙用
  15. MATLAB到底有多厉害?
  16. 第三方登陆--狸菇凉_
  17. python Excel xlsx file; not supported
  18. ShaderJoy —— 用 Shader 绘制一只可爱的 “小挠斧” (详细版)【GLSL】
  19. 【小狗钱钱】—— 送人生一份理财
  20. 北京地铁规划图_测试博客撰写增加图片的办法

热门文章

  1. hdu3666-THE MATRIX PROBLEM【差分约束,自然对数】
  2. jzoj1610(初中)-导弹【最大匹配,最短路,二分答案】
  3. ssl提高组周三备考赛【2018.10.24】
  4. 有上下界网络流问题汇总
  5. 2016陕西省省赛 ACM Rui and her functions B 二分
  6. 这几道 Redis 面试题都不懂,怎么拿 Offer?
  7. 从 Linux 源码看 Socket 的阻塞和非阻塞
  8. Failed to execute
  9. ReviewForJob——算法设计技巧(贪婪算法+分治算法+动态规划)
  10. spring(7)spring mvc 的高级技术