并发之CAS无锁技术
public class Case {
public volatile int n;
public void add() {
n++;
}
}
上述代码中什么变量被volatile修饰,此时说明该变量在多线程操作的情况下可以保证内存的可见性,但是不可以保证原子性操作,因此在多线程并发的时候还是会出现问题的;利用Javap命令来看看汇编指令:
PS D:\ssh> javac Case.java
PS D:\ssh> javap -c Case
Compiled from "Case.java"
public class Case {
public volatile int n; public Case();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return public void add();
Code:
0: aload_0
1: dup
2: getfield #2 // Field n:I
5: iconst_1
6: iadd
7: putfield #2 // Field n:I
10: return
}
PS D:\ssh>
public int a = 1;
public boolean compareAndSwapInt(int b) {
if (a == 1) {
a = b;
return true;
}
return false;
}
上述方法在并发的情况下也是会出现问题的;当多个线程直接进入compareAndSwapInt()之后,他们也同时符合上述的逻辑判断,此时对a的赋值也有可能同事发生,这样也带来了线程安全的问题;
同样加锁的方式也可以解决这个问题,但是在这里我们不研究锁的问题;下面我们来看看一段代码,这是AtomicInteger类中的一部分源码:
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;
/**
* Gets the current value.
*
* @return the current value
*/
public final int get() {
return value;
}
}
int |
addAndGet(int delta) 以原子方式将给定值与当前值相加。 |
在Java8中,这个方法的实现是调用了unsafe()方法;因此我们看不到;
public final int addAndGet(int delta) {
return unsafe.getAndAddInt(this, valueOffset, delta) + delta;
}
但是通过网上看到了该方法的实现方式:
public final int addAndGet(int delta) {
for (;;) {
int current = get();
int next = current + delta;
if (compareAndSet(current, next))
return next;
}
}
public final int get() {
return value;
}
public final boolean compareAndSet(int expect, int update) {
return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
}
并发之CAS无锁技术的更多相关文章
- CAS无锁技术
前言:关于同步,很多人都知道synchronized,Reentrantlock等加锁技术,这种方式也很好理解,是在线程访问的临界区资源上建立一个阻塞机制,需要线程等待 其它线程释放了锁,它才能运行. ...
- 探索CAS无锁技术
前言:关于同步,很多人都知道synchronized,Reentrantlock等加锁技术,这种方式也很好理解,是在线程访问的临界区资源上建立一个阻塞机制,需要线程等待 其它线程释放了锁,它才能运行. ...
- java并发:AtomicInteger 以及CAS无锁算法【转载】
1 AtomicInteger解析 众所周知,在多线程并发的情况下,对于成员变量,可能是线程不安全的: 一个很简单的例子,假设我存在两个线程,让一个整数自增1000次,那么最终的值应该是1000:但是 ...
- (转载)java高并发:CAS无锁原理及广泛应用
java高并发:CAS无锁原理及广泛应用 版权声明:本文为博主原创文章,未经博主允许不得转载,转载请注明出处. 博主博客地址是 http://blog.csdn.net/liubenlong007 ...
- CAS无锁算法与ConcurrentLinkedQueue
CAS:Compare and Swap 比较并交换 java.util.concurrent包完全建立在CAS之上的,没有CAS就没有并发包.并发包借助了CAS无锁算法实现了区别于synchroni ...
- CAS无锁机制原理
原子类 java.util.concurrent.atomic包:原子类的小工具包,支持在单个变量上解除锁的线程安全编程 原子变量类相当于一种泛化的 volatile 变量,能够支持原子的和有条件的读 ...
- CAS无锁实现原理以及ABA问题
CAS(比较与交换,Compare and swap) 是一种有名的无锁算法.无锁编程,即不使用锁的情况下实现多线程之间的变量同步,也就是在没有线程被阻塞的情况下实现变量的同步,所以也叫非阻塞同步(N ...
- CAS无锁操作
https://coolshell.cn/articles/8239.html 主要讲的是<Implementing Lock-Free Queues>的论点,具体直接看论文最好.这里总结 ...
- CAS无锁策略
并发编程时,对于共享资源的使用需要确保绝对的安全性.除了利用锁机制之外,还有一种无锁的概念.所谓无锁,就是假定在并发情况下,对于共享资源的访问没有冲突,线程可以一直不停的运行,无需阻塞,如果产生冲突, ...
随机推荐
- L196 Hospital educations
Surprisingly,no one knows how many children receive education in English hospitals,still less the co ...
- 自定义ViewPagerIndicator
1. 简介 学习Android,自定义View不可避免,之前一直忽视这块内容,现在开始学,应该不算太晚.从常见的ViewPagerIndicator开始,当然,万能的Github上包罗万象,好用的in ...
- Leetcode 1022. Sum of Root To Leaf Binary Numbers
dfs class Solution: def sumRootToLeaf(self, root: TreeNode) -> int: stack=[(root,0)] ans=[] bi_st ...
- start-stop-daemon自动启动、关闭后台程序参数传递
/************************************************************************* * start-stop-daemon自动启动.关 ...
- 1106 1014 C语言文法定义与C程序的推导过程 冒泡程序语法树
- 图形学习 Javascript 正则 regexper.com
regexper.com 可以很方便的显示出正则图示,方便学习正则. 比如正则 ^([a-zA-Z0-9+_-])+@([a-zA-Z_-])+(\.[a-zA-Z0-9_-])+ 一目了然,直观显示 ...
- Apache 多网站配置
直接看实例就清楚了 Listen 80<VirtualHost *:80> DocumentRoot D:/Server/www ServerAdmin webmaster@lifashi ...
- Jquery中的has、find、filter方法区别
find方法 find返回的是匹配结果集,作用于后代$(‘li’).find(‘.a’).css(‘background-color’, ‘red’);在li下面查找元素是否有class=a的元素,返 ...
- shell编写redis启动脚本
安装后redis,默认系统不会自启动,如果关机或重启redis不会自行启动,linux下/etc/init.d/目录下基本上存放所有系统的大多数的启动脚本,放在这个目录下的脚本可以实现自启动操作. ...
- 修改numa和io调度优化mysql性能
一.NUMA设置单机单实例,建议关闭NUMA,关闭的方法有三种:1.硬件层,在BIOS中设置关闭:2.OS内核,启动时设置numa=off:3.可以用numactl命令将内存分配策略修改为interl ...