Java多线程之原子性 volatile、atomicInteger测试
原文链接:http://www.cnblogs.com/zhengbin/p/5653051.html
一、补充概念
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等。
二、实例源码
1 public class IncrementTestDemo {
2
3 public static int count = 0;
4 public static Counter counter = new Counter();
5 public static AtomicInteger atomicInteger = new AtomicInteger(0);
6 volatile public static int countVolatile = 0;
7
8 public static void main(String[] args) {
9 for (int i = 0; i < 10; i++) {
10 new Thread() {
11 public void run() {
12 for (int j = 0; j < 1000; j++) {
13 count++;
14 counter.increment();
15 atomicInteger.getAndIncrement();
16 countVolatile++;
17 }
18 }
19 }.start();
20 }
21 try {
22 Thread.sleep(3000);
23 } catch (InterruptedException e) {
24 e.printStackTrace();
25 }
26
27 System.out.println("static count: " + count);
28 System.out.println("Counter: " + counter.getValue());
29 System.out.println("AtomicInteger: " + atomicInteger.intValue());
30 System.out.println("countVolatile: " + countVolatile);
31 }
32
33 }
34
35 class Counter {
36 private int value;
37
38 public synchronized int getValue() {
39 return value;
40 }
41
42 public synchronized int increment() {
43 return ++value;
44 }
45
46 public synchronized int decrement() {
47 return --value;
48 }
49 }

输出结果:
static count: 9952
Counter: 10000
AtomicInteger: 10000
countVolatile: 9979
第一行与最后一行,每次运行将得到不同的结果,但是中间两行的结果相同。
通过上面的例子说明,要解决自增操作在多线程环境下线程不安全的问题,可以选择使用Java提供的原子类,或者使用synchronized同步方法。
而通过Volatile关键字,并不能解决非原子操作的线程安全性。Volatile详解
三、Java中的自增原理
虽然递增操作++i是一种紧凑的语法,使其看上去只是一个操作,但这个操作并非原子的,因而它并不会作为一个不可分割的操作来执行。实际上,它包含了三个独立的操作:读取count的值,将值加1,然后将计算结果写入count。这是一个“读取 - 修改 - 写入”的操作序列,并且其结果状态依赖于之前的状态。
下面写一个简单的类,用jdk中的工具javap来反编译Java字节码文件。
/**
* @author zhengbinMac
*/
public class TestDemo {
public static int count; public void code() {
count++;
}
}

localhost:Increment zhengbinMac$ javap -c TestDemo
警告: 二进制文件TestDemo包含Increment.TestDemo
Compiled from "TestDemo.java"
public class Increment.TestDemo {
public static int count; public Increment.TestDemo();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return public void code();
Code:
0: getstatic #2 // Field count:I
3: iconst_1
4: iadd
5: putstatic #2 // Field count:I
8: return
}

如上字节码,我们发现自增操作包括取数(getstatic #2)、加一(iconst_1和iadd)、保存(putstatic #2),并不是我们认为的一条机器指令搞定的。
Java多线程之原子性 volatile、atomicInteger测试的更多相关文章
- Java自增原子性问题(测试Volatile、AtomicInteger)
这是美团一面面试官的一个问题,后来发现这是一道面试常见题,怪自己没有准备充分:i++;在多线程环境下是否存在问题?当时回答存在,接着问,那怎么解决?...好吧,我说加锁或者synchronized同步 ...
- Java多线程系列八——volatile和ThreadLocal
参考资料: http://ifeve.com/java-memory-model-4/ http://www.infoq.com/cn/articles/java-memory-model-1 htt ...
- java多线程4:volatile关键字
上文说到了 synchronized,那么就不得不说下 volatile关键字了,它们两者经常协同处理多线程的安全问题. volatile保证可见性 那么volatile的作用是什么呢? 在jvm运行 ...
- java 多线程11:volatile关键字
直接先举一个例子普通的线程实例变量的非可见性: public class MyThread28 extends Thread { private boolean isRunning = true; p ...
- java多线程中的volatile和synchronized
package com.chzhao; public class Volatiletest extends Thread { private static int count = 0; public ...
- Java多线程 -- 正确使用Volatile变量
Java 语言中的 volatile 变量可以被看作是一种 “程度较轻的 synchronized”:与 synchronized 块相比,volatile 变量所需的编码较少,并且运行时开销也较少, ...
- 彻底弄明白之java多线程中的volatile
一. volatite 简述 Java 语言提供了一种稍弱的同步机制,即 volatile 变量.用来确保将变量的更新操作通知到其他线程,保证了新值能立即同步到主内存,以及每次使用前立即从主内存刷新. ...
- java多线程-慎重使用volatile关键字
Java语言包含两种内在的同步机制:同步块(或方法)和 volatile 变量.这两种机制的提出都是为了实现代码线程的安全性.其中 Volatile 变量的同步性较差(但有时它更简单并且开销更低),而 ...
- Java多线程0:核心理论
并发编程是Java程序员最重要的技能之一,也是最难掌握的一种技能.它要求编程者对计算机最底层的运作原理有深刻的理解,同时要求编程者逻辑清晰.思维缜密,这样才能写出高效.安全.可靠的多线程并发程序.本系 ...
随机推荐
- Qt+QGIS二次开发:开发环境搭建(超级详细)
原文链接: 1.qgis二次开发环境搭建(超级详细) 2.QGIS开发教程(1)——QGIS开发准备工作 3.QGIS(2.18.15 源码)+Qt(5/5.9.3)+VS2015(X64)编译
- Matlab使用技巧
(1) Matlab强制退出正在运行的程序A: Ctrl + C(2)如何让Matlab跑完程序后自动关机?A: 在程序的末尾加上一条代码: system('shutdown -s') 当然 ...
- MATLAB——BP神经网络
1.使用误差反向传播(error back propagation )的网络就叫BP神经网络 2.BP网络的特点: 1)网络由多层构成,层与层之间全连接,同一层之间的神经元无连接 . 2)BP网络的传 ...
- MongoDB shell 介绍
MongoDB shell 介绍 MongoDB自带javascript shell, 可在shell中使用命令行与MongoDB实列交互.shell可以执行管理操作,检查运行实列等等操作. 一:如何 ...
- Objective-C 基于Aspects
JavaScriptCore没有禁,因为各种小程序都在用 网络下载文件没有禁
- kubernetes session回话保持
1.Nginx 版本 root@ingress-nginx-controller-4b75b:/# /usr/sbin/nginx -vnginx version: nginx/1.13.9 2.in ...
- ARM架构相关学习归纳总结
ARM作为一个生态不仅提供了CPU Core,还提供了一系列相关的IP,比如GIC.MMU.AMBA.CoreLink.CoreSight.Mali等等. 其他还包括Debug工具.开发工具.IDE等 ...
- SkylineGlobe 6.5 如何实现简单多边形的动态绘制 C#示例代码
在Skyline的TEPro软件中,我们可以很容易地绘制出多边形. 那么,在二次开发过程中,该如何绘制一个简单的多边形呢? 通过下面的示例代码,我们可以很容易完成这一项工作. 其中,重点需要了解Geo ...
- 推荐几本对于Python初学者比较好的书籍(内含PDF)
我们提供一个初学者最好的Python书籍列表.Python是一个初级程序员可以学习编程的最友好语言之一.为了帮助您开始使用Python编程,我们分享此列表.泡一杯茶,选一本书阅读,开始使用Python ...
- YOU AND ME 不见不散(转载)
(看到一篇挺不错的文章,看了挺有感触的,与大家共勉.) 泰戈尔说: 有一个夜晚,我烧毁了所有的记忆, 从此我的梦就透明了: 有个早晨我扔掉了所有的昨天, 从此我的脚步就轻盈了! 越过山丘,才发现无人等 ...