什么是原子操作类
当更新一个变量的时候,多出现数据争用的时候可能出现所意想不到的情况。这时的一般策略是使用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. [Selenium] IOS 之 ios-driver

    从 Selenium 的官方文档来看,推荐用户使用 ios-driver 或 appium 而不是官方发布的 iPone Driver. 他们的地址分别是: http://ios-driver.git ...

  2. MyBatis学习 之 七、mybatis各种数据库的批量修改

      MyBatis的update元素的用法与insert元素基本相同,因此本篇不打算重复了.本篇仅记录批量update操作的sql语句,懂得SQL语句,那么MyBatis部分的操作就简单了. 注意:下 ...

  3. Android应用开发完全退出程序的通用方法

    在开发一个android应用时,有可能有N个Activity,而在每个Activity里的菜单里有个"退出程序"菜单,这里就要完全退出程序了,所以今天给大家分享的是Android应 ...

  4. ASP.NET Core:WebAppCoreApi

    ylbtech-ASP.NET Core:WebAppCoreApi 1.返回顶部 1. 2. 3.           4. 2. Controllers返回顶部 1.ValuesControlle ...

  5. direction

    基本上,大家只要关心下面这两个属性值就好了: direction: ltr; // 默认值 direction: rtl; 其中,ltr是初始值,表示left-to-right,就是从左往右的意思,再 ...

  6. 【旧文章搬运】360安全卫士HookPort.sys完美逆向

    原文发表于百度空间,2009-11-08 这是第一次逆向一个企业级安全产品的核心代码,并完美替换原驱动正常工作============================================= ...

  7. apache日志信息详解

     一.访问日志的格式 Apache内建了记录服务器活动的功能,这就是它的日志功能.下文详细介绍Apache的访问日志.错误日志.以及如何分析日志数据,如何定制Apache日志,如何从日志数据生成统计报 ...

  8. 002--linux基础命令

    退出终端命令:exit 关闭Linux系统的命令:init 0 切换虚拟终端的方法:Ctrl+Alt+F[1-6] who命令 :查看有多少个终端打开着 whoami命令:获取当前用户名 date命令 ...

  9. [转载]OI省选算法汇总

    简单列了一点 1.1 基本数据结构 数组 链表,双向链表 队列,单调队列,双端队列 栈,单调栈 1.2 中级数据结构 堆 并查集与带权并查集 hash 表 自然溢出 双hash 1.3 高级数据结构 ...

  10. 51nod 1133【贪心】

    思路: 按照终点升序,然后遍历一下就好了: #include <bits/stdc++.h> using namespace std; typedef long long LL; cons ...