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就是一种独占锁,会导致其它所有需要锁的线程挂起,等待持有锁的线程释放锁. 乐观锁:每次不加锁,假设没有冲突去完成某项操作,如果因为冲突失败就重试,直到成功 ...
随机推荐
- Spring 相关知识
https://www.bilibili.com/video/BV1gW411W7wy?spm_id_from=333.788.b_636f6d6d656e74.173 老雷的Spring注解驱动 源 ...
- 微服务架构springcloud
码云地址:https://gitee.com/lpxs/lp-springcloud.git 有问题可以多沟通:136358344@qq.com. 微服务架构 一.服务化简介 服务化的核心就是将传统的 ...
- debian10环境安装rtpengine
操作系统 :debian 10.13_x64 rtpengine版本:10.5 最新的debian12环境可通过apt直接安装rtpengine,但工作中有时候还会涉及到debian10这样的老系统, ...
- 利用net-snmp读取windows,linux,snmp设备数据(cpu,内存,网卡)
首先编译的时候configure参数加上--with-mib-modules='ucd-snmp/diskio ip-mib/ipv4InterfaceTable' 默认的配置没有这些模块,需要加上 ...
- 关于捣鼓Gentoo的一些见解
现在很少有人使用gentoo,大家对它的印象都是一个很难用的系统,我想给大家讲讲折腾Gentoo一年的心得,仅供参考 使用archlinux安装盘,genfstab生成fstab 使用gentoo-k ...
- esp32挂esphome
esp32挂esphome 使用docker创建容器 docker run -d --name='esphome' \ --restart=always \ -p 6052:6052 \ -e TZ= ...
- 为什么要使用Java SPI机制
Java SPI(Service Provider Interface)最早是在Java SE 6中被引入的,作为一种标准的.用于在运行时发现和加载服务提供者插件的标准机制.以前的程序猿实现JDBC连 ...
- springjdbc处理nvarchar
当我们使用spring-jdbc来做持久化时(注意不是spring-data-jbc),有时候一些特殊字符存入数据库时会用到nvarchar.nvarchar2这种类型(比如存放化学式,如CO₂等), ...
- Windows 将透明的图片旋转,裁剪
使用 Microsoft Office Picture Manager 本来是想找个Java代码,跑一下 忽然在 Windows 图片打开方式中有一个 Microsoft Office Pictur ...
- 已知两个长度分别为m和n的升序链表,若将它们合并为长度为m+n的一个降序链表,则最坏情况下的时间复杂度是
已知两个长度分别为m和n的升序链表,若将它们合并为长度为m+n的一个降序链表,则最坏情况下的时间复杂度是(). 解析:选D 两个升序合并为降序,操作就不多说了,两数列依次比较放入,其中一个数列结束了, ...