java CAS及各种锁
CAS
CAS
缺点:循环会耗时;一次性只能保持一个共享变量的原子性;ABA问题
package juc.cas;
import java.util.concurrent.atomic.AtomicInteger;
public class CASDemo {
// CAS compareAndSet比较并交换 是CPU的并发原语
public static void main(String[] args) {
AtomicInteger atomicInteger = new AtomicInteger(2020);
// 如果是期望的值就更新,否则一直循环
System.out.println(atomicInteger.compareAndSet(2020, 2021));// true
System.out.println(atomicInteger.get());
atomicInteger.getAndIncrement();// 2021
System.out.println(atomicInteger.compareAndSet(2020, 2021));// false
System.out.println(atomicInteger.get());// 2022
}
}
- ABA问题
package juc.cas;
import java.util.concurrent.atomic.AtomicInteger;
public class CASDemo {
public static void main(String[] args) {
AtomicInteger atomicInteger = new AtomicInteger(2020);
// A对资源操作过了,又改回去了
System.out.println(atomicInteger.compareAndSet(2020, 2021));// true
System.out.println(atomicInteger.get());
System.out.println(atomicInteger.compareAndSet(2021, 2020));// true
System.out.println(atomicInteger.get());
// B不知情
System.out.println(atomicInteger.compareAndSet(2020, 2022));// true
System.out.println(atomicInteger.get());
}
}
- 原子引用解决ABA问题
package juc.cas;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicStampedReference;
public class CASDemo {
public static void main(String[] args) {
// !如果泛型是一个包装类,注意对象的引用问题
// 带版本号的原子操作
AtomicStampedReference<Integer> atomicInteger = new AtomicStampedReference<>(1, 1);
new Thread(()->{
// 获得版本号
System.out.println("A1->" + atomicInteger.getStamp());
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(atomicInteger.compareAndSet(1, 2,
atomicInteger.getStamp(), atomicInteger.getStamp() + 1));
System.out.println("A2->" + atomicInteger.getStamp());
System.out.println(atomicInteger.compareAndSet(2, 1,
atomicInteger.getStamp(), atomicInteger.getStamp() + 1));
System.out.println("A3->" + atomicInteger.getStamp());
},"A").start();
// 乐观锁原理相同
new Thread(()->{
int stamp = atomicInteger.getStamp();// 获得版本号
System.out.println("B1->" + atomicInteger.getStamp());
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(atomicInteger.compareAndSet(1, 6, stamp, stamp + 1));
System.out.println("B2->" + atomicInteger.getStamp());
},"B").start();
}
}
- 注意!:Integer有对象缓存机制
Unsafe类
@IntrinsicCandidate
public final int getAndAddInt(Object o, long offset, int delta) {
int v;
do {
v = getIntVolatile(o, offset);
} while (!weakCompareAndSetInt(o, offset, v, v + delta));// 获取内存地址中的值,自旋锁
return v;
}
public final int getAndIncrement() {
return U.getAndAddInt(this, VALUE, 1);
}
各种锁的理解
- 公平锁:不能插队,必须先来后到
- 非公平锁:可以插队,默认都是非公平
public ReentrantLock() {
sync = new NonfairSync();
}
public ReentrantLock(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();
}
- 可重入锁:拿到外面的锁,就可以拿到里面的锁,自动获得
package juc.lock;
public class Demo1 {
public static void main(String[] args) {
Phone phone = new Phone();
new Thread(()->{
phone.sms();
}, "A").start();
new Thread(()->{
phone.sms();
}, "B").start();
/**
* Asms
* Acall
* Bsms
* Bcall
*/
}
}
class Phone{
public synchronized void sms(){
System.out.println(Thread.currentThread().getName() + "sms");
call();
}
public synchronized void call(){
System.out.println(Thread.currentThread().getName() + "call");
}
}
package juc.lock;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class Demo2 {
public static void main(String[] args) {
Phone2 phone = new Phone2();
new Thread(()->{
phone.sms();
}, "A").start();
new Thread(()->{
phone.sms();
}, "B").start();
/**
* Asms
* Acall
* Bsms
* Bcall
*/
}
}
class Phone2{
Lock lock = new ReentrantLock();
public void sms(){
lock.lock();// 和call的锁不同,是两把锁
try {
System.out.println(Thread.currentThread().getName() + "sms");
call();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void call(){
lock.lock();
try {
System.out.println(Thread.currentThread().getName() + "call");
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
- 自旋锁
package juc.lock;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
public class MySpinlock {
AtomicReference<Thread> atomicReference = new AtomicReference<>();
// 加锁
public void myLock() {
Thread thread = Thread.currentThread();
System.out.println(Thread.currentThread().getName() + " -> mylock");
// 自旋锁
while (!atomicReference.compareAndSet(null, thread)){
}
}
// 解锁
public void myUnLock() {
Thread thread = Thread.currentThread();
System.out.println(Thread.currentThread().getName() + " -> myUnlock");
atomicReference.compareAndSet(thread, null);
}
public static void main(String[] args) throws InterruptedException {
MySpinlock mySpinlock = new MySpinlock();
new Thread(()->{
mySpinlock.myLock();
try {
TimeUnit.SECONDS.sleep(3);
} catch (Exception e) {
e.printStackTrace();
} finally {
mySpinlock.myUnLock();
}
}, "A").start();
TimeUnit.SECONDS.sleep(1);
new Thread(()->{
mySpinlock.myLock();
try {
TimeUnit.SECONDS.sleep(3);
} catch (Exception e) {
e.printStackTrace();
} finally {
mySpinlock.myUnLock();
}
}, "B").start();
/**
* A -> mylock
* B -> mylock
* A -> myUnlock
* B -> myUnlock
*/
}
}
- 死锁
- 使用“jps -l”定位进程号
- 使用“jstack 进程号”寻找死锁问题
java CAS及各种锁的更多相关文章
- Java并发问题--乐观锁与悲观锁以及乐观锁的一种实现方式-CAS
首先介绍一些乐观锁与悲观锁: 悲观锁:总是假设最坏的情况,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会阻塞直到它拿到锁.传统的关系型数据库里边就用到了很 ...
- JAVA CAS原理深度分析 volatile,偏向锁,轻量级锁
JAVA CAS原理深度分析 http://blog.csdn.net/hsuxu/article/details/9467651 偏向锁,轻量级锁 https://blog.csdn.net/zqz ...
- Java 中的各种锁和 CAS + 面试题
Java 中的各种锁和 CAS + 面试题 如果说快速理解多线程有什么捷径的话,那本文介绍的各种锁无疑是其中之一,它不但为我们开发多线程程序提供理论支持,还是面试中经常被问到的核心面试题之一.因此下面 ...
- Java多线程系列--“JUC锁”03之 公平锁(一)
概要 本章对“公平锁”的获取锁机制进行介绍(本文的公平锁指的是互斥锁的公平锁),内容包括:基本概念ReentrantLock数据结构参考代码获取公平锁(基于JDK1.7.0_40)一. tryAcqu ...
- Java多线程系列--“JUC锁”04之 公平锁(二)
概要 前面一章,我们学习了“公平锁”获取锁的详细流程:这里,我们再来看看“公平锁”释放锁的过程.内容包括:参考代码释放公平锁(基于JDK1.7.0_40) “公平锁”的获取过程请参考“Java多线程系 ...
- Java多线程系列--“JUC锁”09之 CountDownLatch原理和示例
概要 前面对"独占锁"和"共享锁"有了个大致的了解:本章,我们对CountDownLatch进行学习.和ReadWriteLock.ReadLock一样,Cou ...
- Java多线程系列--“JUC锁”05之 非公平锁
概要 前面两章分析了"公平锁的获取和释放机制",这一章开始对“非公平锁”的获取锁/释放锁的过程进行分析.内容包括:参考代码获取非公平锁(基于JDK1.7.0_40)释放非公平锁(基 ...
- Java多线程系列--“JUC锁”08之 共享锁和ReentrantReadWriteLock
概要 Java的JUC(java.util.concurrent)包中的锁包括"独占锁"和"共享锁".在“Java多线程系列--“JUC锁”02之 互斥锁Ree ...
- Java多线程系列--“JUC锁”11之 Semaphore信号量的原理和示例
概要 本章,我们对JUC包中的信号量Semaphore进行学习.内容包括:Semaphore简介Semaphore数据结构Semaphore源码分析(基于JDK1.7.0_40)Semaphore示例 ...
- Java CAS 和ABA问题
独占锁:是一种悲观锁,synchronized就是一种独占锁,会导致其它所有需要锁的线程挂起,等待持有锁的线程释放锁. 乐观锁:每次不加锁,假设没有冲突去完成某项操作,如果因为冲突失败就重试,直到成功 ...
随机推荐
- WSL启动nvidia-docker镜像:报错libnvidia-ml.so.1- file exists- unknown
参考: https://blog.csdn.net/xujiamin0022016/article/details/124782913 https://zhuanlan.zhihu.com/p/361 ...
- baselines算法库common/vec_env/util.py模块分析
util.py模块代码: """ Helpers for dealing with vectorized environments. """ ...
- 读论文《Reinforced Attention for Few-Shot Learning and Beyond》
2022年4月22日,实验室开组会,我讲了论文<Reinforced Attention for Few-Shot Learning and Beyond>,最近整理资料又再读了一遍,这里 ...
- php 开发日常收获
最近项目需求: 仿制某网站的菜单功能 效果如下: 效果大概就是这样啦.分析下吧:主要是分级查询我的思路:首先从数据库中查询所有的顶级目录: 目前就是这几个顶级目录在数据库中特点就是 父级id是0(一般 ...
- MySQL编译安装-麒麟V10 x86
环境信息 操作系统: Kylin Linux Advanced Server V10 (Sword) 架构:X86 MySQL版本:5.7.44 编译 安装必要的依赖库和编译工具 sudo yum g ...
- 深度解析HarmonyOS SDK实况窗服务源码,Get不同场景下的多种模板
HarmonyOS SDK实况窗服务(Live View Kit)作为一个实时呈现应用服务信息变化的小窗口,遍布于设备的各个使用界面,它的魅力在于将复杂的应用场景信息简洁提炼并实时刷新,在不影响当前其 ...
- 【Burp Suite】Mac之破解明文密码
一.安装CA证书 安装证书是为了代理的时候可以继续访问地址,否则的话会提示网络异常 参考文章:<Mac系统Burp Suite的安装>,文章中是火狐浏览器的操作 1.谷歌浏览器 选择导出的 ...
- 用MySQL的GROUP_CONCAT函数轻松解决多表联查的聚合问题
大家好呀,我是summo,最近遇到了一个功能需求,虽然也是CURD,但属于那种比较复杂一点的CURD,话不多说,我们先看一下需求. 需求如下: 有三张表,学生表.课程表.学生课程关联表,关联关系如下图 ...
- TimeWheel算法介绍及在应用上的探索
作者:来自 vivo 互联网服务器团队- Li Fan 本文从追溯时间轮算法的出现,介绍了时间轮算法未出现前,基于队列的定时任务实现,以及基于队列的定时任务实现所存在的缺陷.接着我们介绍了时间轮算法的 ...
- ggml 简介
ggml 是一个用 C 和 C++ 编写.专注于 Transformer 架构模型推理的机器学习库.该项目完全开源,处于活跃的开发阶段,开发社区也在不断壮大.ggml 和 PyTorch.Tensor ...