Java之多线程内存可见性_2(volatile不能保证原子性)
2015-12-17 14:16
627 查看
以下内容在慕课网-->细说Java多线程之内存可见性
volatile不能保证原子性
实际执行结果不一定是500
因为:不能保证原子性,可能多个线程交叉执行
number++ 不是原子性
如:
number = 5
1.线程A读取number的值
2.线程B读取number的值
3.线程B执行加1操作
4.线程B写入最新的number的值
主内存:number = 6
线程B工作内存:number = 6
线程A工作内存:number = 5
5.线程A执行加1操作
6.线程A写入最新的number值,主内存的number = 6
7.整个过程2次number++实际上只加了1
解决方案:
保证number自增操作的原子性:
1.使用synchronized关键字
2.使用ReentrantLock(java.until.concurrent.locks包下, jdk1.5)
3.使用AtomicInterger(vava.util.concurrent.atomic包下, jdk1.5)
使用synchronized解决
修改:
1.
2.
使用ReentrantLock解决 :
修改:
1.增加
2.
volatile适合场合
要在多线程中安全的使用volatile变量,必须同时满足”
1.对变量的写入操作不依赖其当前值(改变后的值不能与之前的值有关系)
如:不满足:number++ count = count*5等
满足:boolean变量、记录温度变化的变量等
2.该变量没有包含在具有其他变量的不变式中(有多个volatile变量,每个volatile变量状态独立于其他volatile变量)
如:程序中有2个volatile变量low,up
不满足:不变式low<up
volatile不能保证原子性
public class VolatileDemo{ private volatile int number = 0; public int getNumber(){ return this.number; } public void increase(){ this.number++; } public static void main(String[], args){ final VolatileDemo volDemo = new VolatileDemo(); for(int i=0; i<500;i++) { new thread(new Runnable(){ public void run(){ volDemo.increase(); } }).start(); } //如果还有子线程在运行,主线陈就让出cpu资源, //知道所有的子线程都运行完了,主线程再继续往下执行 while(Thread.activiCount() > 1){ Thread.yield(); } System.out.println("number:" + volDemo.getNumber()); } }
实际执行结果不一定是500
因为:不能保证原子性,可能多个线程交叉执行
public void increase(){ this.number++; }
number++ 不是原子性
如:
number = 5
1.线程A读取number的值
2.线程B读取number的值
3.线程B执行加1操作
4.线程B写入最新的number的值
主内存:number = 6
线程B工作内存:number = 6
线程A工作内存:number = 5
5.线程A执行加1操作
6.线程A写入最新的number值,主内存的number = 6
7.整个过程2次number++实际上只加了1
解决方案:
保证number自增操作的原子性:
1.使用synchronized关键字
2.使用ReentrantLock(java.until.concurrent.locks包下, jdk1.5)
3.使用AtomicInterger(vava.util.concurrent.atomic包下, jdk1.5)
使用synchronized解决
修改:
1.
private volatile int number = 0; 修改为private int number = 0;
2.
public void increase(){ synchronized(this){ this.number++; } }
使用ReentrantLock解决 :
修改:
1.增加
private Lock lock = new ReentrantLock();
2.
public void increase(){ lock.lock();//加锁 try{ //推荐写法 this.number++; }finally{//锁内部操作可能会抛出一些异常,所以保证锁一定能被释放 lock.unlock();//解锁 } }
volatile适合场合
要在多线程中安全的使用volatile变量,必须同时满足”
1.对变量的写入操作不依赖其当前值(改变后的值不能与之前的值有关系)
如:不满足:number++ count = count*5等
满足:boolean变量、记录温度变化的变量等
2.该变量没有包含在具有其他变量的不变式中(有多个volatile变量,每个volatile变量状态独立于其他volatile变量)
如:程序中有2个volatile变量low,up
不满足:不变式low<up
相关文章推荐
- Spring mvc+hibernate+freemarker(实战)
- Java关键字
- eclipse中安装Kotlin插件后的问题
- spring对javamail的封装使用
- java swing设置背景颜色的问题
- Java 定时任务Timer
- java环境配置
- jdk代理
- Levenshtein Distance算法(java实现)
- 轻量级JavaEE企业应用实战(七)
- 使用注解和自定义验证实现Spring MVC表单验证(翻译)
- java资料——哈希表(散列表)(转)
- 转 Java 获取和判断文件头信息
- 【Struts2】(9)国际化
- Spring中如何配置Hibernate事务
- Eclipse Java注释模板设置详解
- Mybatis3源码分析(03)-加载Configuration-ResultMap说明
- Java获取当前路径
- Java并发编程:线程池的使用
- ubuntu下安装java和eclipse