Java并发编程实践笔记之—可见性(Visibility)
来源:互联网 发布:越南新娘淘宝 编辑:程序博客网 时间:2024/06/15 01:46
同步的重要性有两个方面:
- 实现原子性:防止某个线程正在使用对象状态而另一个线程同时在修改改状态
- 内存可见性:确保一个线程修改了对象状态后,其他线程能够看到发生的状态变化
失效数据
- 缺乏同步的程序可能会产生的一种错误情况就是——失效数据
- 失效数据举例
//在没有同步的情况下共享数据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; }}
引发的问题有
- NoVisibility 可能会持续循环下去,因为ReaderThread可能永远看不到ready写入的值
- NoVisibility 可能会输出0,因为ReaderThread可能看到了ready写入的值,但是没有看到写入的number的值(这种现象叫重排序)
非原子的64位操作
- 非volatile类型的64位数值变量(double和long)在多线程程序中使用也是不安全的
- 如果对该变量的读操作和写操作在不同的线程中执行,那么可能会读取某个值的高32位和另一个值的低32位
- 用关键字volatile来声明,或者用锁保护
加锁与可见性
- 为了确保所有线程都能看到共享变量的最新值,所有执行读操作或者写操作的线程都必须在同一个锁上同步
volatile变量
- 稍弱的同步机制
- 编译器和runtime都会注意到这个变量是共享的,所以不会将该变量重排序,不会被缓存在寄存器或者其他处理器不可见的地方
- 行为类似于以下程序清单,但是使用volatile时不会执行加锁操作,因此也不会阻塞线程,比synchronized更轻量级
@ThreadSafe public class SynchronizedInteger { @GuardedBy("this") private int value; public synchronized int get() { return value; } public synchronized void set(int value) { this.value = value; } }
- 仅当volatile变量能简化代码的实现以及对同步策略的验证时,才应该使用它们,不建议过度依赖volatile变量提供的可见性
- 通常用作某个操作完成、发生中断或者状态的标志
- 典型用法:检查某个状态标记以判断是否退出循环。以下示例中asleep必须为volatile变量,否则当asleep被另一个线程修改时,执行判断的线程却发现不了。
- 加锁机制可以确保可见性和原子性,而volatile变量只能确保可见性
//数绵羊volatile boolean asleep; ... while (!asleep) countSomeSheep();
0 0
- Java并发编程实践笔记之—可见性(Visibility)
- Java并发编程实践笔记(四)——chapter3(重排序优化,可见性)
- Java并发编程之可见性问题
- Java并发编程实战学习笔记(二)-可见性
- Java并发编程实践笔记之—不变性(Immutability)
- Java并发编程实践笔记之—线程
- 《Java Concurrency in Practice》之可见性(Visibility)
- Java并发编程实践笔记之-并发简史
- JavaSE初学笔记之<并发编程—内存模型、可见性、原子性>
- Java并发编程实践笔记之——活跃性和性能(Liveness and Performance)
- Java并发编程实践笔记之——原子性(Atomicity)
- java并发编程实践笔记
- java并发编程实践笔记
- java并发编程实践笔记
- java并发编程实践笔记
- java并发编程实践笔记
- java并发编程实践笔记
- java并发编程实践笔记
- MjRefresh在Xcode6.0上的问题
- Java并发编程实践笔记之—发布和逸出(Publication and Escape)
- jQuery 学习一(基础知识)
- poj 2538 WERTYU
- 两个周期信号之和、乘积是否是周期信号的讨论
- Java并发编程实践笔记之—可见性(Visibility)
- 2015-1-28工作日志
- 注解型SpringMvc为基础的框架设计(一)
- Java并发编程实践笔记之——活跃性和性能(Liveness and Performance)
- get和post的区别
- jQuery 学习二(核心函数)
- Android 调试技巧全面总结(持续更新)
- Java并发编程实践笔记之——用锁来保护状态(Guarding State with Locks)
- jQuery 学习三(对象访问)