java并发编程系列二:原子操作/CAS
什么是原子操作
不可被中断的一个或者一系列操作
实现原子操作的方式
Java可以通过锁和循环CAS的方式实现原子操作
CAS( Compare And Swap ) 为什么要有CAS?
Compare And Swap就是比较并且交换的一个原子操作,由Cpu在指令级别上进行保证。
为什么要有CAS:因为通过锁实现原子操作时,其他线程必须等待已经获得锁的线程运行完以后才能获得资源,这样就会占用系统的大量资源
CAS包含哪些参数?
CAS包含三个参数:1、变量所在内存地址V;2、变量对应的值A;3、我们将要修改的值B。如果说V上的变量的值是A的话,就用B重新赋值,如果不是A,那就什么事也不做,操作的返回结果原值是多少。
循环CAS:在一个(死)循环【for(;;)】里不断进行CAS操作,直到成功为止(自旋操作即死循环)。
CAS实现原子操作的三大问题
1、 ABA问题:其他的线程把值改成了B,很快改成了A,原子操作的线程发现值是A就修改,这样会有问题。解决ABA,引入版本号:1A-》2C-》3A
2、 循环时间很长的话,cpu的负荷比较大
3、 对一个变量进行操作可以,同时操作多个共享变量有点麻烦
CAS线程安全(面试点)
通过硬件层面的阻塞实现原子操作的安全
原子更新基本类型类
AtomicBoolean、AtomicInteger、AtomicLong、AtomicReference。
AtomicInteger的常用方法如下
·int addAndGet(int delta):
·boolean compareAndSet(int expect,int update):
·int getAndIncrement(): 原子递增,但是返回的是自增以前的值
incrementAndGet原子递增,但是返回的是自增以后的值
·int getAndSet(int newValue):
package com.lgs.atomicint; import java.util.concurrent.atomic.AtomicInteger; /**
* lgs
* 原子操作更新整型
*/
public class AtomicIntTest {
static AtomicInteger ai = new AtomicInteger(1);
public static void main(String[] args) {
System.out.println(ai.getAndIncrement());
ai.incrementAndGet();
System.out.println(ai.get());
}
}
输出:
1
3
原子更新数组类
AtomicIntegerArray,AtomicLongArray,AtomicReferenceArray
AtomicIntegerArray类主要是提供原子的方式更新数组里的整型,
其常用方法如下。
·int addAndGet(int i,int delta):
·boolean compareAndSet(int i,int expect,int update):
数组通过构造方法传入,类会将数组复制一份,原数组不会发生变化。
package com.lgs.atomicarray; import java.util.concurrent.atomic.AtomicIntegerArray; /**
* lgs
* 原子操作更新数组
*/
public class AtomicArray {
static int[] value = new int[]{1,2};
static AtomicIntegerArray ai = new AtomicIntegerArray(value); public static void main(String[] args) {
ai.getAndSet(0,3);
System.out.println(ai.get(0));
System.out.println(value[0]);
} }
输出:
3
1
原子更新引用类型提供的类。
·AtomicReference: 可以解决更新多个变量的问题
·AtomicStampedReference:解决ABA问题 使用数字作为版本 关心得是有几个人改过
·AtomicMarkableReference:解决ABA问题 使用Boolean作为版本,关心的是有没有修改过
package com.lgs; import java.util.concurrent.atomic.AtomicReference; /**
* lgs
* 原子操作更新引用类型即可以同时更新多个值
*/
public class AtomicRef { static AtomicReference<User> userAtomicReference = new AtomicReference<>(); public static void main(String[] args) {
User user = new User("lgs",26);
userAtomicReference.set(user);
User updateUser = new User("ll",27);
userAtomicReference.compareAndSet(user,updateUser);
System.out.println(userAtomicReference.get().getName());
System.out.println(userAtomicReference.get().getOld());
} static class User{
private String name;
private int old; public User(String name, int old) {
this.name = name;
this.old = old;
} public String getName() {
return name;
} public int getOld() {
return old;
}
} }
输出:
ll
27
原子更新字段类
Atomic包提供了以下3个类进行原子字段更新。
·AtomicReferenceFieldUpdater:
·AtomicIntegerFieldUpdater:
·AtomicLongFieldUpdater:
违反了面向对象的原则,一般不使用
java并发编程系列二:原子操作/CAS的更多相关文章
- Java并发编程系列-(3) 原子操作与CAS
3. 原子操作与CAS 3.1 原子操作 所谓原子操作是指不会被线程调度机制打断的操作:这种操作一旦开始,就一直运行到结束,中间不会有任何context switch,也就是切换到另一个线程. 为了实 ...
- Java并发编程系列-(5) Java并发容器
5 并发容器 5.1 Hashtable.HashMap.TreeMap.HashSet.LinkedHashMap 在介绍并发容器之前,先分析下普通的容器,以及相应的实现,方便后续的对比. Hash ...
- Java并发编程系列-(4) 显式锁与AQS
4 显示锁和AQS 4.1 Lock接口 核心方法 Java在java.util.concurrent.locks包中提供了一系列的显示锁类,其中最基础的就是Lock接口,该接口提供了几个常见的锁相关 ...
- Java并发编程系列-(2) 线程的并发工具类
2.线程的并发工具类 2.1 Fork-Join JDK 7中引入了fork-join框架,专门来解决计算密集型的任务.可以将一个大任务,拆分成若干个小任务,如下图所示: Fork-Join框架利用了 ...
- Java并发编程系列-(1) 并发编程基础
1.并发编程基础 1.1 基本概念 CPU核心与线程数关系 Java中通过多线程的手段来实现并发,对于单处理器机器上来讲,宏观上的多线程并行执行是通过CPU的调度来实现的,微观上CPU在某个时刻只会运 ...
- Java并发编程系列-(6) Java线程池
6. 线程池 6.1 基本概念 在web开发中,服务器需要接受并处理请求,所以会为一个请求来分配一个线程来进行处理.如果每次请求都新创建一个线程的话实现起来非常简便,但是存在一个问题:如果并发的请求数 ...
- Java并发编程系列-(7) Java线程安全
7. 线程安全 7.1 线程安全的定义 如果多线程下使用这个类,不过多线程如何使用和调度这个类,这个类总是表示出正确的行为,这个类就是线程安全的. 类的线程安全表现为: 操作的原子性 内存的可见性 不 ...
- Java并发编程系列-(8) JMM和底层实现原理
8. JMM和底层实现原理 8.1 线程间的通信与同步 线程之间的通信 线程的通信是指线程之间以何种机制来交换信息.在编程中,线程之间的通信机制有两种,共享内存和消息传递. 在共享内存的并发模型里,线 ...
- Java并发编程系列-(9) JDK 8/9/10中的并发
9.1 CompletableFuture CompletableFuture是JDK 8中引入的工具类,实现了Future接口,对以往的FutureTask的功能进行了增强. 手动设置完成状态 Co ...
随机推荐
- Status: Checked in and viewable by authorized users 出现在sharepoint 2013 home 页面
点击home页面上方的publish-> publishing->publish
- Word Ladder - LeetCode
目录 题目链接 注意点 解法 小结 题目链接 Word Ladder - LeetCode 注意点 每一个变化的字母都要在wordList中 解法 解法一:bfs.类似走迷宫,有26个方向(即26个字 ...
- Raid卷详解
#RAID卷 独立磁盘冗余阵列RAID是一种把多块独立的硬盘(物理硬盘)按不同的方式组合起来形成一个硬盘组(逻辑硬盘),从而提供比单个硬盘更高的存储性能和提供数据备份技术.组成磁盘阵列的不同方式成为R ...
- luogu2024 食物链 (并查集)
把一个点拆成三个,分别对应它的同类.它的猎物和它的天敌,这样的话(以下的相等都是并查集意义上的): 如果令a,b同类,那么a的猎物不能是b的同类,a的天敌不能是b的同类 如果令a吃b,那么a的同类不能 ...
- detectMultiScale 读取冲突的一个解决方法
背景:用的是opencv的HOGDescriptor检测行人,实例化为hog:使用默认的行人检测器: hog.setSVMDetector(cv::HOGDescriptor::getDefaultP ...
- Java -- JDBC 学习--处理Blob
Oracle LOB LOB,即Large Objects(大对象),是用来存储大量的二进制和文本数据的一种数据类型(一个LOB字段可存储可多达4GB的数据).LOB 分为两种类型:内部LOB和外部L ...
- luogu P2181 对角线
题目大意: 给一个n边形,求出在所有任意三条对角线都不相交于同一个点的情况下,交点个数是多少.(即交点个数最多是多少) 分析: 题目很水,但是公式不好想. 由于任意三条对角线不会交于一点,所以所有的交 ...
- javascript:location.reload()和location.replace()的区别,及对图片缓存的影响。
有段时间没有清理IE的临时文件(缓存文件),在我清理的时候,我突然发现一个问题. 我打开的一个网站,图片默认缓存一个月的,但我发现,当我上传图片或删除图片之后,图片重新缓存,也就意味着,在我上传新图片 ...
- 线程优先级.Priority()
线程对象.Priority(),线程优先级1-10,10优先级最高.此功能比较鸡肋,不起作用.了解即可 以下案例:循环输出加减乘除,除优先级最高 //MyThread线程 class MyThread ...
- 选择监听事件ItemListener(是否被选择)
[界面说明] 下拉列表框,选谁谁显示.复选框与单选按钮,输出被选与否的状态.知识点主要代码为: int state = e.getStateChange(); ItemEvent.SELECTED I ...