并发之AtomicInteger
package automic; public class AtomicIntegerTest extends Thread{ private Integer count=0;
@Override
public void run() {
for(int i=1;i<=500;i++){
count++;
}
System.out.println("count的值是:"+ count); } public static void main(String[] args) {
AtomicIntegerTest a=new AtomicIntegerTest();
Thread t1 = new Thread(a);
Thread t2 = new Thread(a);
t1.start();
t2.start(); } }
package automic; import java.util.concurrent.atomic.AtomicInteger; public
class AtomicIntegerTest2 extends Thread{
/**
* 这里使用了AtomicInteger类,这是一个对于变量可以进行原子性操作的类;核心是CAS无锁算法;
* 下面两个构造器其中一个进行了值得初始化
* public AtomicInteger(int initialValue) {
* value = initialValue;
* }
* public AtomicInteger() {
* }
*/ private AtomicInteger count=new AtomicInteger(0);
@Override
public void run() {
for(int i=1;i<=500;i++){
/**
* getAndIncrement是以原子的方式给当前值加1
*/
count.getAndIncrement();
}
System.out.println("count的值是:"+ count); } public static void main(String[] args) {
AtomicIntegerTest2 a=new AtomicIntegerTest2();
Thread t1 = new Thread(a);
Thread t2 = new Thread(a);
t1.start();
t2.start(); } }
public class AtomicInteger extends Number implements java.io.Serializable {
private static final long serialVersionUID = 6214790243416807050L; // setup to use Unsafe.compareAndSwapInt for updates
private static final Unsafe unsafe = Unsafe.getUnsafe();
private static final long valueOffset;
}
static {
try {
valueOffset = unsafe.objectFieldOffset
(AtomicInteger.class.getDeclaredField("value"));
} catch (Exception ex) { throw new Error(ex); }
}
private volatile int value;
public final int getAndIncrement() {
for (;;) {
int current = get();
int next = current + 1;
if (compareAndSet(current, next))
return current;
}
}
在看看jdk1.8的源码:
public final int getAndIncrement() {
return unsafe.getAndAddInt(this, valueOffset, 1);
}
使用了unsafe的方法,其实二者底层的实现方式都差不多;进入一个for循环,不断的比较内存值和期望值,如果相等就修改,不相等就返回false;
/**
* set()方法 ,设置一个值
*/
public final void set(int newValue) {
value = newValue;
} /**
* lazySet()方法,没有storeload屏障的set,出现于JDK1.6
*/
public final void lazySet(int newValue) {
unsafe.putOrderedInt(this, valueOffset, newValue);
} /**
* getAndSet()方法 原子性的获取并且设置值
*/
public final int getAndSet(int newValue) {
return unsafe.getAndSetInt(this, valueOffset, newValue);
} /**
* 如果当前值和内存值相等,那么进行更新
*/
public final boolean compareAndSet(int expect, int update) {
return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
} /**
* weak的CAS,也就是没有volatile语义的CAS,没有加入内存屏障
*/
public final boolean weakCompareAndSet(int expect, int update) {
return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
} /**
* 自增加,返回原来的值.
*/
public final int getAndIncrement() {
return unsafe.getAndAddInt(this, valueOffset, 1);
} /**
* 自减少,返回原来的值
*/
public final int getAndDecrement() {
return unsafe.getAndAddInt(this, valueOffset, -1);
} /**
* 原子性的增加delta的值
*/
public final int getAndAdd(int delta) {
return unsafe.getAndAddInt(this, valueOffset, delta);
} /**
* 自增1
*/
public final int incrementAndGet() {
return unsafe.getAndAddInt(this, valueOffset, 1) + 1;
} /**
* 自减1
*/
public final int decrementAndGet() {
return unsafe.getAndAddInt(this, valueOffset, -1) - 1;
} /**
* 阻塞式更新,并且对prev进行一个IntUnaryOperator操作运算
*/
public final int updateAndGet(IntUnaryOperator updateFunction) {
int prev, next;
do {
prev = get();
next = updateFunction.applyAsInt(prev);
} while (!compareAndSet(prev, next));
return next;
} /**
* 阻塞式更新,并对prev和x,进行二元运算操作。于jdk1.8出现
*/
public final int getAndAccumulate(int x,
IntBinaryOperator accumulatorFunction) {
int prev, next;
do {
prev = get();
next = accumulatorFunction.applyAsInt(prev, x);
} while (!compareAndSet(prev, next));
return prev;
}
上述的一些方法的解释:
2)StoreLoad // 这个是所有内存屏障里最耗性能的
并发之AtomicInteger的更多相关文章
- 并发之atomicInteger与CAS机制
并发之atomic与CAS自旋锁 通过前几章的讲解我们知道i++这种类似操作是不安全的.针对这种情况,我们可能会想到利用synchronize关键字实现线程同步,保证++操作的原子性,的确这是一种有效 ...
- Java自增原子性问题(测试Volatile、AtomicInteger)
这是美团一面面试官的一个问题,后来发现这是一道面试常见题,怪自己没有准备充分:i++;在多线程环境下是否存在问题?当时回答存在,接着问,那怎么解决?...好吧,我说加锁或者synchronized同步 ...
- 并发之java.util.concurrent.atomic原子操作类包
15.JDK1.8的Java.util.concurrent.atomic包小结 14.Java中Atomic包的原理和分析 13.java.util.concurrent.atomic原子操作类包 ...
- 并发之线程封闭与ThreadLocal解析
并发之线程封闭与ThreadLocal解析 什么是线程封闭 实现一个好的并发并非易事,最好的并发代码就是尽量避免并发.而避免并发的最好办法就是线程封闭,那什么是线程封闭呢? 线程封闭(thread c ...
- 并发之Striped64(l累加器)
并发之Striped64(累加器) 对于该类的实现思想: Striped64是在java8中添加用来支持累加器的并发组件,它可以在并发环境下使用来做某种计数,Striped64的设计思路 ...
- java并发之阻塞队列LinkedBlockingQueue与ArrayBlockingQueue
Java中阻塞队列接口BlockingQueue继承自Queue接口,并提供put.take阻塞方法.两个主要的阻塞类实现是ArrayBlockingQueue和LinkedBlockingQueue ...
- java高并发之线程池
Java高并发之线程池详解 线程池优势 在业务场景中, 如果一个对象创建销毁开销比较大, 那么此时建议池化对象进行管理. 例如线程, jdbc连接等等, 在高并发场景中, 如果可以复用之前销毁的对 ...
- 微信公众号开发之VS远程调试
目录 (一)微信公众号开发之VS远程调试 (二)微信公众号开发之基础梳理 (三)微信公众号开发之自动消息回复和自定义菜单 前言 微信公众平台消息接口的工作原理大概可以这样理解:从用户端到公众号端一个流 ...
- Android混合开发之WebViewJavascriptBridge实现JS与java安全交互
前言: 为了加快开发效率,目前公司一些功能使用H5开发,这里难免会用到Js与Java函数互相调用的问题,这个Android是提供了原生支持的,不过存在安全隐患,今天我们来学习一种安全方式来满足Js与j ...
随机推荐
- Python入门及安装
简介 是用来编写应用程序的高级编程语言,"内置电池",哲学:简单优雅,尽量写容易看明白的代码,尽量写少的代码,适合干嘛:网络应用.网站.后台服务:日常些工具,如系统管理员需要的脚本 ...
- App Store下载Mac应用失败的解决办法
1. 更换DNS服务器 国内可以用alidns: 223.5.5.5 223.6.6.6 也可以用电信的: 114.114.114.114 国外的可以考虑Google 8.8.8.8 8.8.4.4 ...
- AI探索(二)Tensorflow环境准备
Python + Tensorflow环境安装 Tensorflow支持Windows/Mac/Linux等三种操作系统, 其中windows下python需要安装3.5以上的版本 Mac/Linux ...
- python--关于if __name__==__main__的解释
在解释之前首先我们看下__name__这个变量存的是什么: #!/usr/bin/env python # -*- coding:utf-8 -*- print(__name__) 结果: __mai ...
- metaclass 了解一下
创建类的两种方式 方式一: class Foo(object,metaclass=type): CITY = "bj" def func(self,x): return x + 1 ...
- python究竟要不要使用多线程
在总结concurrent.futures库之前先来弄明白三个问题: (1)python多线程究竟有没有用? (2)python虚拟机机制如何控制代码的执行? (3)python中多进程处理原理是怎么 ...
- Python 2.7_利用xpath语法爬取豆瓣图书top250信息_20170129
大年初二,忙完家里一些事,顺带有人交流爬取豆瓣图书top250 1.构造urls列表 urls=['https://book.douban.com/top250?start={}'.format(st ...
- ExtJs中获得当前选中行号(Grid中多选或者是单选)及Grid的反选(取消选中行)
多选,如何获得每行的行号: function getlineNum(){ var sm=titleGird.getSelectionModel(); // 获得grid的SelectionMod ...
- CentOS7.2 GitLab部署
1.使用安装包的方式安装gitlab # vim /etc/yum.repos.d/gitlib.repo [gitlab-ce] name=gitlab-ce baseurl=http://mirr ...
- Linux应用函数 -- 字符串
1.strchr 原型 char *strchr(const char* _Str,char _Val) 头文件 string.h 功能 查找字符串_Str中首次出现字符_Val的位置 返回值 成功 ...