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就是一种独占锁,会导致其它所有需要锁的线程挂起,等待持有锁的线程释放锁. 乐观锁:每次不加锁,假设没有冲突去完成某项操作,如果因为冲突失败就重试,直到成功 ...
随机推荐
- 【转载】 Visual Studio Code几款FTP插件使用总结
===================================================== 平时要维护类似wordpress这样的网站,然后虚拟主机又不支持远程仓的版本管理.总而言之, ...
- 手写一个AQS实现
1.背景 1.AQS简介AQS全称为AbstractQueuedSynchronizer(抽象队列同步器).AQS是一个用来构建锁和其他同步组件的基础框架,使用AQS可以简单且高效地构造出应用广泛的同 ...
- 面试官:JDK中都用了哪些设计模式?
设计模式是前辈们经过实践验证总结的解决方案,帮助我们构建出更具可维护性.可扩展性和可读性的代码.当然,在面试的过程中,也会或多或少的被问到.那么今天,我们就来看一道设计模式中的常见面试问题:JDK 中 ...
- ARM汇编:MRS和MSR指令
1.MSR和MRS指令介绍 MRS 指令: 对状态寄存器CPSR和SPSR进行读操作.通过读CPSR可以获得当前处理器的工作状态.读SPSR寄存器可以获得进入异常前的处理器状态(因为只有异常模式下有 ...
- LLM应用实战: 产业治理多标签分类
1. 背景 许久未见,甚是想念~ 近期本qiang~换了工作,处于新业务适应期,因此文章有一段时间未更新,理解万岁! 现在正在着手的工作是产业治理方面,主要负责其中一个功能模块,即按照产业治理标准体系 ...
- Kubernetes-11:ConfigMap介绍及演示
ConfigMap存在的意义 ConfigMap 功能在 Kubernetes1.2版本引入,许多应用程序会从配置文件.命令行参数或环境变量中读取配置信息,ConfigMap API 给我们提供了向容 ...
- 注册中心Nacos集群搭建
一提到注册中心,大家往往想到Zookeeper.或者Eureka.今天我们看看阿里的一款配置中心+注册中心的中间件--Nacos.有了它以后,我们的项目中的配置就可以统一从Nacos中获取了,而且Sp ...
- 5.5文件上传-WAF绕过
一.WAF绕过(明确有文件上传) 1.上传参数中,可修改参数 Content-Dispositin:一般可改 name:表单参数,不可更改 filename:文件名,可更改 Content-Type: ...
- netcore高级知识点,内存对齐,原理与示例
最近几年一直从事物联网开发,与硬件打交道越来越多,发现越接近底层开发对性能的追求越高,毕竟硬件资源相对上层应用来实在是太缺乏了.今天想和大家一起分享关于C#中的内存对齐,希望通过理解和优化内存对齐,可 ...
- sharepoint 打开rdl报表,报表服务器数据库内出错。此错误可能是因连接失败、超时或数据库中磁盘空间不足而导致的
最近在做reporting services报表的时候,部署到sharepoint后,打开rdl报表,经常遇到一个问题: 报表服务器数据库内出错.此错误可能是因连接失败.超时或数据库中磁盘空间不足而导 ...