Java自增原子性问题(测试Volatile、AtomicInteger)
来源:互联网 发布:淘宝上代写代发论文 编辑:程序博客网 时间:2024/06/08 02:13
这是美团一面面试官的一个问题,后来发现这是一道面试常见题,怪自己没有准备充分:i++;在多线程环境下是否存在问题?当时回答存在,接着问,那怎么解决?。。。好吧,我说加锁或者synchronized同步方法。接着问,那有没有更好的方法?
经过一番百度、谷歌,还可以用AtomicInteger这个类,这个类提供了自增、自减等方法(如i++或++i都可以实现),这些方法都是线程安全的。
一、补充概念
1.什么是线程安全性?
《Java Concurrency in Practice》中有提到:当多个线程访问某个类时,这个类始终都能表现出正确的行为,那么就称这个类是线程安全的。
2.Java中的“同步”
Java中的主要同步机制是关键字“synchronized”,它提供了一种独占的加锁方式,但“同步”这个术语还包括volatile类型的变量,显式锁(Explicit Lock)以及原子变量。
2.原子性
原子是世界上的最小单位,具有不可分割性。比如 a=0;(a非long和double类型)这个操作是不可分割的,那么我们说这个操作时原子操作。再比如:a++;这个操作实际是a = a + 1;是可分割的,所以他不是一个原子操作。非原子操作都会存在线程安全问题,需要我们使用同步技术(sychronized)来让它变成一个原子操作。一个操作是原子操作,那么我们称它具有原子性。java的concurrent包下提供了一些原子类,我们可以通过阅读API来了解这些原子类的用法。比如:AtomicInteger、AtomicLong、AtomicReference等。
+ View codepublic class IncrementTestDemo { public static int count = 0; public static Counter counter = new Counter(); public static AtomicInteger atomicInteger = new AtomicInteger(0); volatile public static int countVolatile = 0; public static void main(String[] args) { for (int i = 0; i < 10; i++) { new Thread() { public void run() { for (int j = 0; j < 1000; j++) { count++; counter.increment(); atomicInteger.getAndIncrement(); countVolatile++; } } }.start(); } try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("static count: " + count); System.out.println("Counter: " + counter.getValue()); System.out.println("AtomicInteger: " + atomicInteger.intValue()); System.out.println("countVolatile: " + countVolatile); } }class Counter { private int value; public synchronized int getValue() { return value; } public synchronized int increment() { return ++value; } public synchronized int decrement() { return --value; }}
static count: 9952Counter: 10000AtomicInteger: 10000countVolatile: 9979
第一行与最后一行,每次运行将得到不同的结果,但是中间两行的结果相同。
通过上面的例子说明,要解决自增操作在多线程环境下线程不安全的问题,可以选择使用Java提供的原子类,或者使用synchronized同步方法。
而通过Volatile关键字,并不能解决非原子操作的线程安全性。Volatile详解
三、Java中的自增原理
虽然递增操作++i是一种紧凑的语法,使其看上去只是一个操作,但这个操作并非原子的,因而它并不会作为一个不可分割的操作来执行。实际上,它包含了三个独立的操作:读取count的值,将值加1,然后将计算结果写入count。这是一个“读取 - 修改 - 写入”的操作序列,并且其结果状态依赖于之前的状态。
- Java自增原子性问题(测试Volatile、AtomicInteger)
- Java自增原子性问题(测试Volatile、AtomicInteger)
- Java多线程之原子性 volatile、atomicInteger、synchronized测试
- volatile AtomicInteger java多线程操作 原子性
- java 线程原子问题 AtomicInteger
- Java并发编程:volatile关键字解析(原子性问题)
- java 原子变量AtomicInteger
- 原子变量AtomicInteger (volatile深入分析 . Atomic:原子变量与原子类 .)
- Volatile、AtomicInteger、java并发
- java 多线程 AtomicInteger原子变量
- Java 原子操作类详解(AtomicInteger、AtomicIntegerArray等)
- java volatile应用之 AtomicInteger
- java原子性以及关键字volatile、synchronized
- java volatile double、long的原子性
- Java volatile变量原子性讨论
- Java原子操作AtomicInteger的用法
- 原子性操作类AtomicInteger等
- 原子性和volatile
- Eclipse的使用简介
- JavaWeb三大组件之一Servlet【访问量统计-ServletContext的应用】
- arcgis servie10.3 发布缓存服务
- Python爬虫基础之百度翻译的实现
- leetcode 349. Intersection of Two Arrays
- Java自增原子性问题(测试Volatile、AtomicInteger)
- 判断app一个APP页面是原生的还是H5页面
- pat说反话(java)
- Ubuntu 14.04 下读取CPU温度
- Carthage管理依赖库
- 详解spring 每个jar的作用
- android 跳转到手机内存中查找文件,并上传音频文件
- 获取android软键盘高度
- LeetCode 57 Insert Interval