什么是原子操作类
当更新一个变量的时候,多出现数据争用的时候可能出现所意想不到的情况。这时的一般策略是使用synchronized解决,因为synchronized能够保证多个线程不会同时更新该变量。然而,从jdk 5之后,提供了粒度更细、量级更轻,并且在多核处理器具有高性能的原子操作类。因为原子操作类把竞争的范围缩小到单个变量上,这可以算是粒度最细的情况了。

原子操作类相当于泛化的volatile变量,能够支持原子读取-修改-写操作。比如AtomicInteger表示一个int类型的数值,提供了get和set方法,这些volatile类型的变量在读取与写入上有着相同的内存语义。原子操作类共有13个类,在java.util.concurrent.atomic包下,可以分为四种类型的原子更新类:原子更新基本类型、原子更新数组类型、原子更新引用和原子更新属性。

下面介绍这各种原子操作类
1 原子更新基本类型:使用原子方式更新基本类型

AtomicBoolean:原子更新布尔变量
AtomicInteger:原子更新整型变量
AtomicLong:原子更新长整型变量
2 原子更新数组:通过原子更新数组里的某个元素

AtomicIntegerArray:原子更新整型数组的某个元素
AtomicLongArray:原子更新长整型数组的某个元素
AtomicReferenceArray:原子更新引用类型数组的某个元素
3 原子更新引用类型:更新引用类型

AtomicReference:原子更新引用类型
AtomicReferenceFieldUpdater:原子更新引用类型里的字段
AtomicMarkableReference:原子更新带有标记位的引用类型
4 原子更新字段:原子更新某个类的某个字段

AtomicIntegerFieldUpdater:原子更新整型字段
AtomicLongFieldUpdater:原子更新长整型字段
AtomicStampedReference:原子更新带有版本号的引用类型
我们接下来会通过对AtomicInteger的讲解来深入认识原子操作类
在单线程环境下,执行num++等操作时不会出现问题,那么,在多线程环境下是否还是跟单线程环境下一样安全呢?我们通过一段代码进行模拟。

public class Demo {

private static int num = 0;

public static void add() {
num++;
}

public static void main(String[] args) {
Thread[] myThread = new Thread[10];
for(Thread thread : myThread) {
thread = new Thread() {
@Override
public void run() {
for(int i = 0;i < 1000;i++) {
add();
}
}
};
thread.start();
}

while (Thread.activeCount() > 1) {
Thread.yield();
}
System.out.println(num);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
我们进行三次测试,得出结果分别是

8400
8318
9856

在没有同步条件下,自增操作不具备原子性,在多线程环境下是不安全的。

既然我们上面的方法不安全,那该咋办呢,总不能坐以待毙吧?没事,我们有一件新武器,那就是AtomicInteger原子类型。把上面的代码改为使用AtomicInteger,让我们看看接下来会发生什么?

import java.util.concurrent.atomic.AtomicInteger;

public class Demo {

public static AtomicInteger num = new AtomicInteger(0);

public static void add() {
num.incrementAndGet();
}

public static void main(String[] args) {
Thread[] myThread = new Thread[10];
for(Thread thread : myThread) {
thread = new Thread() {
@Override
public void run() {
for(int i = 0;i < 1000;i++) {
add();
}
}
};
thread.start();
}

while (Thread.activeCount() > 1) {
Thread.yield();
}
System.out.println(num);
}
}
---------------------

Java并发编程之原子操作类的更多相关文章

  1. Java并发编程:Thread类的使用

    Java并发编程:Thread类的使用 在前面2篇文章分别讲到了线程和进程的由来.以及如何在Java中怎么创建线程和进程.今天我们来学习一下Thread类,在学习Thread类之前,先介绍与线程相关知 ...

  2. 【转】Java并发编程:Thread类的使用

    一.线程的状态 在正式学习Thread类中的具体方法之前,我们先来了解一下线程有哪些状态,这个将会有助于对Thread类中的方法的理解. 线程从创建到最终的消亡,要经历若干个状态.一般来说,线程包括以 ...

  3. 3、Java并发编程:Thread类的使用

    Java并发编程:Thread类的使用 在前面2篇文章分别讲到了线程和进程的由来.以及如何在Java中怎么创建线程和进程.今天我们来学习一下Thread类,在学习Thread类之前,先介绍与线程相关知 ...

  4. java并发编程之原子操作

    先来看一段简单的代码,稍微有点并发知识的都可以知道打印出结果必然是一个小于20000的值 package com.example.test.cas; import java.io.IOExceptio ...

  5. Java并发编程:Thread类的使用介绍

    在学习Thread类之前,先介绍与线程相关知识:线程的几种状态.上下文切换,然后接着介绍Thread类中的方法的具体使用. 以下是本文的目录大纲: 一.线程的状态 二.上下文切换 三.Thread类中 ...

  6. Java并发编程:Thread类的使用(转载)

    一:线程的状态: 在正式学习Thread类中的具体方法之前,我们先来了解一下线程有哪些状态,这个将会有助于后面对Thread类中的方法的理解. 线程从创建到最终的消亡,要经历若干个状态.一般来说,线程 ...

  7. java并发编程 - Exexctors 工具类

    Executors 类提供了一系列静态工厂方法用于创建各种线程池. newFixedThreadPool 创建固定大小的线程池.每次提交一个任务就创建一个线程,直到线程达到线程池的最大大小.线程池的大 ...

  8. Java并发编程-总纲

    Java 原生支持并发,基本的底层同步包括:synchronized,用来标示一个方法(普通,静态)或者一个块需要同步执行(某一时刻,只允许一个线程在执行代码块).volatile,用来标识一个变量是 ...

  9. java并发编程目录

    java并发编程目录 Java多线程基础:进程和线程之由来 JAVA多线程实现的四种方式 Java并发编程:线程间协作的两种方式:wait.notify.notifyAll和Condition Jav ...

随机推荐

  1. BZOJ_2726_[SDOI2012]任务安排_斜率优化+二分

    BZOJ_2726_[SDOI2012]任务安排_斜率优化+二分 Description 机器上有N个需要处理的任务,它们构成了一个序列.这些任务被标号为1到N,因此序列的排列为1,2,3...N.这 ...

  2. 生产环境下搭建mongodb复制集高可用环境(python)

    环境描述:有三台ubuntu服务器,,每台服务器上已经有mongodb实例.创建3个mongo2.4的新实例,分别作为三个复制集节点,同时保证了当前单节点环境的稳定 3台服务器都已经有单个mongo实 ...

  3. redhat 关机注销命令详解

    一.注销,关机,重启 注销系统的logout命令 1,Logout 注销是登陆的相对操作,登陆系统后,若要离开系统,用户只要直接下达logout命令即可: [root@localhost root]# ...

  4. 在linux下用tomcat部署java web项目的过程与注意事项(转)

    在linux下用tomcat部署java web项目的过程与注意事项一.安装JDK到http://www.oracle.com/technetwork/java/javase/downloads/in ...

  5. 学习笔记::kmp

    matrix67 nxt[i]:[1-i]中最长公共前后缀的长度 j=0;;i<=n;i++) { ]) j=nxt[j]; ]) j++; nxt[i]=j; }

  6. c++中.c_str和.c_data

    1 关于.c_str的用法: const char *c_str(); 这个数组的数据是临时的,当有一个改变这些数据的成员函数被调用后,其中的数据就会失效.因此要么现用先转换,要么把它的数据复制到用户 ...

  7. 4种java复制文件的方式

    尽管Java提供了一个可以处理文件的IO操作类,但是没有一个复制文件的方法.复制文件是一个重要的操作,当你的程序必须处理很多文件相关的时候.然而有几种方法可以进行Java文件复制操作,下面列举出4中最 ...

  8. hadoop中的序列化

    此文已由作者肖凡授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 最近在学习hadoop,发现hadoop的序列化过程和jdk的序列化有很大的区别,下面就来说说这两者的区别都有 ...

  9. <TLE>奇偶剪枝hdoj1010

    (奇偶剪枝)转自百度百科,讲的非常棒: http://baike.baidu.com/link?url=3g5bW7LszRVOVvFDFp6cL0ZZnAaOLUdpaNjc2leHoxkKU9Eh ...

  10. P5154 数列游戏(区间dp)

    传送门 果然和dp有关的东西我绝对做不出来啊-- 设\(dp[i][j]\)表示消完区间\([i,j]\)中的数之后能得到的最大分数,如果消不完则为\(-inf\),否则枚举断点.顺便如果\(a[i] ...