原文链接: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 }

  输出结果:

+ View code
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测试的更多相关文章

  1. Java自增原子性问题(测试Volatile、AtomicInteger)

    这是美团一面面试官的一个问题,后来发现这是一道面试常见题,怪自己没有准备充分:i++;在多线程环境下是否存在问题?当时回答存在,接着问,那怎么解决?...好吧,我说加锁或者synchronized同步 ...

  2. Java多线程系列八——volatile和ThreadLocal

    参考资料: http://ifeve.com/java-memory-model-4/ http://www.infoq.com/cn/articles/java-memory-model-1 htt ...

  3. java多线程4:volatile关键字

    上文说到了 synchronized,那么就不得不说下 volatile关键字了,它们两者经常协同处理多线程的安全问题. volatile保证可见性 那么volatile的作用是什么呢? 在jvm运行 ...

  4. java 多线程11:volatile关键字

    直接先举一个例子普通的线程实例变量的非可见性: public class MyThread28 extends Thread { private boolean isRunning = true; p ...

  5. java多线程中的volatile和synchronized

    package com.chzhao; public class Volatiletest extends Thread { private static int count = 0; public ...

  6. Java多线程 -- 正确使用Volatile变量

    Java 语言中的 volatile 变量可以被看作是一种 “程度较轻的 synchronized”:与 synchronized 块相比,volatile 变量所需的编码较少,并且运行时开销也较少, ...

  7. 彻底弄明白之java多线程中的volatile

    一. volatite 简述 Java 语言提供了一种稍弱的同步机制,即 volatile 变量.用来确保将变量的更新操作通知到其他线程,保证了新值能立即同步到主内存,以及每次使用前立即从主内存刷新. ...

  8. java多线程-慎重使用volatile关键字

    Java语言包含两种内在的同步机制:同步块(或方法)和 volatile 变量.这两种机制的提出都是为了实现代码线程的安全性.其中 Volatile 变量的同步性较差(但有时它更简单并且开销更低),而 ...

  9. Java多线程0:核心理论

    并发编程是Java程序员最重要的技能之一,也是最难掌握的一种技能.它要求编程者对计算机最底层的运作原理有深刻的理解,同时要求编程者逻辑清晰.思维缜密,这样才能写出高效.安全.可靠的多线程并发程序.本系 ...

随机推荐

  1. js之省市区(县)三级联动效果

    省市区(县)三级联动效果,是我们软件开发比较常用的,特别是对一些crm,erp之类,当然也包括其他的后台管理系统,基本都涉及到,今天贴出这个常用的,方便个人复用和大家使用 <!DOCTYPE h ...

  2. spring batch批量处理框架

    spring batch精选,一文吃透spring batch批量处理框架 前言碎语 批处理是企业级业务系统不可或缺的一部分,spring batch是一个轻量级的综合性批处理框架,可用于开发企业信息 ...

  3. 『转』MySQL存储过程语法例子

    原文地址:http://blog.chinaunix.net/uid-540802-id-138873.html ------------------------- 自动生成随机数据存储过程 ---- ...

  4. Unity 消息管理(观察煮模式)

    一.首先定义一份消息号(消息号用来标记发出的每一条消息,接收者通过注册要监听的消息号来监听相应的消息) public enum MSG_IDS { NONE = -, MSG_TEST01 = , M ...

  5. 【LGR-048 五周年庆贺】洛谷6月月赛

    Luogu的五周年庆典比赛,还是比较满意的. 题目清新不毒瘤,数据优质不卡常,解法自然,为出题人点赞. 前三题的难度都很低,T5个人感觉还好.但是最后那个splay+hash是什么神仙东西. 最后好像 ...

  6. [Spark][Python]DataFrame的左右连接例子

    [Spark][Python]DataFrame的左右连接例子 $ hdfs dfs -cat people.json {"name":"Alice",&quo ...

  7. 5分钟入门自动化测试——你应该学会的Postman用法(2)

    前言 之前的一篇文章<你应该学会的Postman用法>,主要介绍了postman的一些高级的用法,便于日常开发和调试使用,本文的基础是对postman的基本使用以及一些高级用法有一定的了解 ...

  8. Timer计时不准确的问题及解决方法

    在项目中,需要每隔20ms发送一个RTP数据包.一开始使用的是System.Windows.Forms下的Timer类,但是发现明显延迟了.用StopWatch测了一下,发现它的触发间隔居然不是20m ...

  9. Html5计算MD5值

    教程: http://www.tuicool.com/articles/InEBNz 组件: https://github.com/satazor/js-spark-md5

  10. 北航学堂Android客户端Beta阶段测试报告

    我们已经知道的bug如下: 1.在没有网络的情况下,我们的程序会直接崩溃,没有弹出提醒网络异常的错误,这是个比较严重的bug,我们在6号7号 考试结束之后会进行修改: 有待进行的优化: 1.UI界面的 ...