Java并发下的count++问题
来源:互联网 发布:js获取自定义标签的值 编辑:程序博客网 时间:2024/06/07 18:45
需要深入理解volatile请看方腾飞的博客:
http://ifeve.com/volatile/
引用自 http://www.cnblogs.com/aigongsi/archive/2012/04/01/2429166.html
Java中的原子操作包括:
- 除long和double之外的基本类型的赋值操作
- 所有引用reference的赋值操作
- java.concurrent.Atomic.* 包中所有类的一切操作
count++不是原子操作,是3个原子操作组合:
- 读取主存中的count值,赋值给一个局部成员变量tmp
- tmp+1
- 将tmp赋值给count
可能会出现线程1运行到第2步的时候,tmp值为1;这时CPU调度切换到线程2执行完毕,count值为1;切换到线程1,继续执行第3步,count被赋值为1————结果就是两个线程执行完毕,count的值只加了1;
还有一点要注意,如果使用AtomicInteger.set(AtomicInteger.get()+1),会和上述情况一样有并发问题,要使用AtomicInteger.getAndIncrement()才可以避免并发问题
package com.lianglin.test;
public class VolatileTest {
static class MyObject{
static int mycount=0;
}
public static void inc() {
MyObject.mycount++;
}
public static void main(String[] args) {
//同时启动1000个线程,去进行i++计算,看看实际结果
for (int i = 0; i < 1000; i++) {
new Thread(new Runnable() {
@Override
public void run() {
inc();
}
}).start();
}
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
};
//这里每次运行的值都有可能不同,可能为1000
System.out.println(“运行结果:Counter.count=” +MyObject.mycount);
}
}
每次输出值都是:1000
注意:
对于值引用来说,多线程操作的是变量的副本,操作完后刷新到主存中。而对于地址引用,多线程是通过地址操作的是同一个变量。volatitle关键字告诉编译器,直接去通过地址操作变量,而不是变量的副本
2016-01-22更新使用volatitle关键字:jvm虚拟机只是保证从主内存加载到线程工作内存的值是最新的,意即还是变量的副本.
一切重点都在于对于值引用来说,线程保存的是值的副本!如果count =1 ,
在走到第二步拷贝值到本地后,如果cpu切换到另一个线程完成了 count++ 那么内存中的count = 2
而此时第一个线程的副本还是1,此时再做count++并赋值给内存中的count,相当于并没有+1,只是重复赋值了一次
- Java并发下的count++问题
- java 的并发问题
- 高并发下接口的并发问题
- Java并发小结(在公司遇到并发下问题的总结--1)
- Java的并发问题总结
- Java并发的基础问题
- 多并发下数据保存的问题
- 数据库并发下的脏数据问题
- 高并发下出现的一个问题
- java基础解析系列(五)---HashMap并发下的问题以及HashTable和CurrentHashMap的区别
- java基础解析系列(五)---HashMap并发下的问题以及HashTable和CurrentHashMap的区别
- Count(*)和Count(1)的问题
- 【Java 高并发】并发下的ArrayList&&HashMap
- 从DCL问题出发认识并发环境下的Java内存访问
- java高并发下对象创建过多出现的内存问题
- java/android下的并发编程
- Java Concurrent包下的并发容器
- java并发包下的LockSupport
- 揭开网络编程常见API的面纱【下】
- GVIM 简单配置
- @Autowired与@Resource的区别
- android 获取顶部状态栏 信息 高度
- Super关键字
- Java并发下的count++问题
- Longest Consecutive Sequence
- iPhone屏幕尺寸、分辨率及适配
- 8天学通MongoDB——第四天 索引操作
- 如何看待操作系统的用户空间和内核空间?
- MySQL主键的理解
- window.open 不会重复开启窗口
- Android进程间通信之使用Messenger
- (转)Java并发编程之内存模型与volatile关键字解析