Java并发编程原理与实战十三:JDK提供的原子类原理与使用
原子更新基本类型
原子更新数组
原子更新抽象类型
原子更新字段
原子更新基本类型:
package com.roocon.thread.t8; import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicIntegerArray; public class Sequence {
private AtomicInteger value = new AtomicInteger(0);
private int [] s = {2,1,4,6};
AtomicIntegerArray a = new AtomicIntegerArray(s); public int getNext(){
a.getAndIncrement(2);//给下标为2的元素加1
a.getAndAdd(2, 10);//获取下标为2的元素,并且加10
for (int i=0; i < a.length(); i++){
System.out.println(a.get(i));
}
return value.getAndIncrement();
} public static void main(String[] args) {
Sequence sequence = new Sequence();
new Thread(new Runnable() {
@Override
public void run() {
while (true){
System.out.println(Thread.currentThread().getName()+" "+sequence.getNext());
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
while (true){
System.out.println(Thread.currentThread().getName()+" "+sequence.getNext());
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
while (true){
System.out.println(Thread.currentThread().getName()+" "+sequence.getNext());
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
}
}
运行结果:
Thread-0 0
Thread-1 1
Thread-2 2
Thread-0 3
Thread-1 4
Thread-2 5
...
package com.roocon.thread.t8; import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicIntegerArray;
import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
import java.util.concurrent.atomic.AtomicReference; public class Sequence {
private AtomicInteger value = new AtomicInteger(0);
AtomicReference<User> user = new AtomicReference<>(); //对user的set和get执行原子操作
AtomicIntegerFieldUpdater<User> old = AtomicIntegerFieldUpdater.newUpdater(User.class, "old"); public int getNext(){
User user = new User();
System.out.println(old.getAndIncrement(user));
System.out.println(old.getAndIncrement(user));
System.out.println(old.getAndIncrement(user));
return value.getAndIncrement();
} public static void main(String[] args) {
Sequence sequence = new Sequence();
new Thread(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+" "+sequence.getNext());
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
}
}
运行结果:
0
1
2
Thread-0 0
对CAS的源码理解:--初步理解
在AtomicInteger中有这样一段源码:
public final int getAndUpdate(IntUnaryOperator updateFunction) {
int prev, next;
do {
prev = get();
next = updateFunction.applyAsInt(prev);
} while (!compareAndSet(prev, next));
return prev;
}
public final boolean compareAndSet(int expect, int update) {
return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
}
其中,compareAndSwap就是CAS的缩写。如果prev和next不相等,则返回true。否则,返回false。最终是通过unsafe来实现的。
以上代码表示,如果compareAndSet返回true,则while条件为false,退出循环,返回prev值。如果compareAndSet返回false,则while为true,继续执行循环体,重新获取prev的值,重新获取更新值,直到返回的compareAndSet值为true。
演示源码大致步骤如下:
Object prev = get(); //
next = prev + 1;
boolean flag = cas(prev, next);
if (flag) {
return prev;
}else {
go to 1
} Object pre
参考资料:
《java并发编程与实战》龙果学院
Java并发编程原理与实战十三:JDK提供的原子类原理与使用的更多相关文章
- 并发编程学习笔记(4)----jdk5中提供的原子类及Lock使用及原理
(1)jdk中原子类的使用: jdk5中提供了很多原子类,它会使变量的操作变成原子性的. 原子性:原子性指的是一个操作是不可中断的,即使是在多个线程一起操作的情况下,一个操作一旦开始,就不会被其他线程 ...
- JDK提供的原子类原理与使用
原子更新基本类型 原子更新数组 原子更新抽象类型 原子更新字段 原子更新基本类型: package com.roocon.thread.t8; import java.util.concurrent. ...
- 转:【Java并发编程】之二十三:并发新特性—信号量Semaphore(含代码)
载请注明出处:http://blog.csdn.net/ns_code/article/details/17524153 在操作系统中,信号量是个很重要的概念,它在控制进程间的协作方面有着非常重要的作 ...
- JDK提供的原子类和AbstractQueuedSynchronizer(AQS)
大致分成: 1.原子更新基本类型 2.原子更新数组 3.原子更新抽象类型 4.原子更新字段 import java.util.concurrent.atomic.AtomicInteger; impo ...
- Java并发编程原理与实战二十:线程安全性问题简单总结
一.出现线程安全性问题的条件 •在多线程的环境下 •必须有共享资源 •对共享资源进行非原子性操作 二.解决线程安全性问题的途径 •synchronized (偏向锁,轻量级锁,重量级锁) •vol ...
- Java并发编程原理与实战三十三:同步容器与并发容器
1.什么叫容器? ----->数组,对象,集合等等都是容器. 2.什么叫同步容器? ----->Vector,ArrayList,HashMap等等. 3.在多线程环境下,为什么不 ...
- Java并发编程原理与实战三十一:Future&FutureTask 浅析
一.Futrue模式有什么用?------>正所谓技术来源与生活,这里举个栗子.在家里,我们都有煮菜的经验.(如果没有的话,你们还怎样来泡女朋友呢?你懂得).现在女票要你煮四菜一汤,这汤是鸡汤, ...
- Java并发编程原理与实战二十五:ThreadLocal线程局部变量的使用和原理
1.什么是ThreadLocal ThreadLocal顾名思义是线程局部变量.这种变量和普通的变量不同,这种变量在每个线程中通过get和set方法访问, 每个线程有自己独立的变量副本.线程局部变量不 ...
- Java并发编程原理与实战十:单例问题与线程安全性深入解析
单例模式我想这个设计模式大家都很熟悉,如果不熟悉的可以看我写的设计模式系列然后再来看本文.单例模式通常可以分为:饿汉式和懒汉式,那么分别和线程安全是否有关呢? 一.饿汉式 先看代码: package ...
随机推荐
- 《构建之法》第8,9,10章读后感&sprint1个人总结
第8章 这一章主要介绍需求分析.具体说明了软件需求的类型.利益相关者,获取用户需求分析的常用方法与步骤.竞争性需求分析的框架NABCD,四象限方法以及项目计划和估计的技术.需求分析是决定一个软件的使用 ...
- java 调用 oracle的function 和 procedure
1.调用函数 CallableStatement cs=con.prepareCall("{?=call get_pname(?,?,?)}"); 第一个?表示返回的值,后面的?可 ...
- curl 实例详解
使用PHP的cURL库可以简单和有效地去抓网页.你只需要运行一个脚本,然后分析一下你所抓取的网页,然后就可以以程序的方式得到你想要的数据 了.无论是你想从从一个链接上取部分数据,或是取一个XML文件并 ...
- [官网]SQLSERVER ON linux 的最低要求 以及安装方法
快速入门:在 Red Hat 上安装 SQL Server 并创建数据库 总体说明: 适用于: SQL Server (仅限 Linux)Azure SQL 数据库Azure SQL 数据仓库并行数据 ...
- Thinkphp面试问题
1.如何理解TP中的单一入口文件? 答:ThinkPHP采用单一入口模式进行项目部署和访问,无论完成什么功能,一个项目都有一个统一(但不一定是唯一)的入口.应该说,所有项目都是从入口文件开始的,并且所 ...
- Redis(一) 安装
选择在Linux下安装redis,现在采用虚拟机安装的centos7 进行安装的 1.安装gcc yum install gcc-c++ 2.下载redis安装包,在root目录下执行 wget ht ...
- echarts 地图 离线json包分享
最近,项目中需要用到地图,由于项目的特殊性,只能使用内网获取数据. 然而,echarts官网上的离线地图包(http://echarts.baidu.com/download-map.html)早在一 ...
- 回车”(carriage return)和”换行”(line feed)的区别和来历-(附:ASCII表)
这两天研究小票打印机编程手册,遇到这样一个问题: LF,即Line Feed,中文意思“换行”:CR,即Carriage Return,中文意思“回车”.但是我们通常把这两个混为一谈.既然设置 ...
- P2461 [SDOI2008]递归数列
题目描述 一个由自然数组成的数列按下式定义: 对于i <= k:ai = bi 对于i > k: ai = c1ai-1 + c2ai-2 + ... + ckai-k 其中bj 和 cj ...
- 【刷题】BZOJ 3551 [ONTAK2010]Peaks加强版
Description [题目描述]同3545 Input 第一行三个数N,M,Q. 第二行N个数,第i个数为h_i 接下来M行,每行3个数a b c,表示从a到b有一条困难值为c的双向路径. 接下来 ...