java中的Atomic类
java中的Atomic类
问题背景
在多线程环境中,我们最常遇到的问题就是变量的值进行同步。因为变量需要在多线程中进行共享,所以我们必须需要采用一定的同步机制来进行控制。
通过之前的文章,我们知道可以采用Lock的机制,当然也包括今天我们讲的Atomic类。
下面我们从两种方式来分别介绍。
Lock
在之前的文章中,我们也讲了同步的问题,我们再回顾一下。 如果定义了一个计数器如下:
public class Counter {
int counter;
public void increment() {
counter++;
}
}
如果是在单线程环境中,上面的代码没有任何问题。但是如果在多线程环境中,counter++将会得到不同的结果。
因为虽然counter++看起来是一个原子操作,但是它实际上包含了三个操作:读数据,加一,写回数据。
我们之前的文章也讲了,如何解决这个问题:
public class LockCounter {
private volatile int counter;
public synchronized void increment() {
counter++;
}
}
通过加synchronized,保证同一时间只会有一个线程去读写counter变量。
通过volatile,保证所有的数据直接操作的主缓存,而不使用线程缓存。
这样虽然解决了问题,但是性能可能会受影响,因为synchronized会锁住整个LockCounter实例。
使用Atomic
通过引入低级别的原子化语义命令(比如compare-and-swap (CAS)),从而能在保证效率的同时保证原子性。
一个标准的CAS包含三个操作:
- 将要操作的内存地址M。
- 现有的变量A。
- 新的需要存储的变量B。
CAS将会先比较A和M中存储的值是否一致,一致则表示其他线程未对该变量进行修改,则将其替换为B。 否则不做任何操作。
使用CAS可以不用阻塞其他的线程,但是我们需要自己处理好当更新失败的情况下的业务逻辑处理情况。
Java提供了很多Atomic类,最常用的包括AtomicInteger, AtomicLong, AtomicBoolean, 和 AtomicReference.
其中的主要方法:
- get() – 直接中主内存中读取变量的值,类似于volatile变量。
- set() – 将变量写回主内存。类似于volatile变量。
- lazySet() – 延迟写回主内存。一种常用的情景是将引用重置为null的情况。
- compareAndSet() – 执行CAS操作,成功返回true,失败返回false。
- weakCompareAndSet() – 比较弱的CAS操作,不同的是它不执行happens-before操作,从而不保证能够读取到其他变量最新的值。
我们看下怎么用:
public class AtomicCounter {
private final AtomicInteger counter = new AtomicInteger(0);
public int getValue() {
return counter.get();
}
public void increment() {
while(true) {
int existingValue = getValue();
int newValue = existingValue + 1;
if(counter.compareAndSet(existingValue, newValue)) {
return;
}
}
}
}
本文的例子可以参考https://github.com/ddean2009/learn-java-concurrency/tree/master/atomic
更多教程请参考 flydean的博客
java中的Atomic类的更多相关文章
- 【Java并发】Java中的原子操作类
综述 JDK从1.5开始提供了java.util.concurrent.atomic包. 通过包中的原子操作类能够线程安全地更新一个变量. 包含4种类型的原子更新方式:基本类型.数组.引用.对象中字段 ...
- java中的原子操作类AtomicInteger及其实现原理
/** * 一,AtomicInteger 是如何实现原子操作的呢? * * 我们先来看一下getAndIncrement的源代码: * public final int getAndIncremen ...
- 带有静态方法的类(java中的math类)
带有静态方法的类通常(虽然不一定是这样)不打算被初始化. 可以用私有构造函数来限制非抽象类被初始化. 例如,java中的math类.它让构造函数标记为私有,所以你无法创建Math的实例.但Math类却 ...
- java中的File类
File类 java中的File类其实和文件并没有多大关系,它更像一个对文件路径描述的类.它即可以代表某个路径下的特定文件,也可以用来表示该路径的下的所有文件,所以我们不要被它的表象所迷惑.对文件的真 ...
- Java基础(43):Java中的Object类与其方法(转)
Object类 java.lang.Object java.lang包在使用的时候无需显示导入,编译时由编译器自动导入. Object类是类层次结构的根,Java中所有的类从根本上都继承自这个类. O ...
- java中基于TaskEngine类封装实现定时任务
主要包括如下几个类: 文章标题:java中基于TaskEngine类封装实现定时任务 文章地址: http://blog.csdn.net/5iasp/article/details/10950529 ...
- Java中的Unsafe类111
1.Unsafe类介绍 Unsafe类是在sun.misc包下,不属于Java标准.但是很多Java的基础类库,包括一些被广泛使用的高性能开发库都是基于Unsafe类开发的,比如Netty.Hadoo ...
- Java中遍历实体类(处理MongoDB)
在实际过程中,经常要将实体类进行封装,尤其是处理数据库的过程中:因此,对于遍历实体类能够与数据库中的一行数据对应起来. 我是使用的环境是Spring boot,访问的数据库时MongoDB 实体类遍历 ...
- java中遍历实体类,获取属性名和属性值
方式一(实体类): //java中遍历实体类,获取属性名和属性值 public static void testReflect(Object model) throws Exception{ for ...
随机推荐
- error: cannot bind non-const lvalue reference of type
这种问题一般是因为引用了匿名变量.涉及左值和右值的区别.一般函数的参数如果是一个表达式,那将会产生一个第3方的匿名变量传入这个函数中,此时如果引用,没用什么实际意义. c++中临时变量不能作为非con ...
- mui在vue_cli上使用
在main.js里添加 import mui from './assets/js/mui.js' 如果不添加下面会显示mui is not defined 报错 Vue.prototype.mui = ...
- Android如何快速打出100个渠道apk
测试1分钟900多个包 关键思路就是读文件,如图: Python快速打包脚本: #!/usr/bin/env python import zipfile prefix = 'channel_' cha ...
- uni_app商城项目(完成)
总结: 1.uni-app的跨段适配性,真的特别强,完成相关代码的书写,HbuilderX编辑器提供的打包十分方便. 2.开发小程序,H5等移动端开发, 比开发电脑端简单不少,但有时候坑也挺多的. 3 ...
- JQUERY滚动加载
$(document).height():整个网页的高度$(window).height():浏览器可视窗口的高度$(window).scrollTop():浏览器可视窗口顶端距离网页顶端的高度(垂直 ...
- 基于my-DAQ的温室迷你温室设计
这是一个小项目,采用NI的my-DAQ做数据采集,需要采集的数据有温度(LM35),气体(MQ2),需要控制的设备有风扇.加热棒,另外还有光照亮度调节. 一.数据采集 1.LM35 LM35是模拟输出 ...
- ValidForm.js的使用注意点
dataType的值不能为"", 否则会导致错误发生:Uncaught TypeError: Cannot read property '0' of null,http请求可以发送 ...
- Obtain The String CodeForces - 1295C binary_search+思维
妈耶,,,被B题卡到哭,C题一发就过了... 字符串问题.首先用vector记录每个字符出现的位置,然后对字符串t的每个字符,用二分查找函数查找,注意用upper_bound查找,对于字符i,首先用变 ...
- G - Can you find it? 二分
Give you three sequences of numbers A, B, C, then we give you a number X. Now you need to calculate ...
- Cucumber(4)——jenkins的集成
目录 回顾 必备知识 集成方法 回顾 在上几节中,关于cucumber的知识我已经全部的介绍完了,但是近期,jenkins大行其道,在工作上面能为我们节省大量的时间. 所以在本节中,我会介绍cucum ...