Java~今日学习各种锁策略(乐观锁 悲观锁 读写锁等等)、CAS机制和synchronize的原理及其优化机制(锁消除 偏向锁 自旋锁 膨胀锁 锁粗化)(1)

import java.util.concurrent.atomic.AtomicInteger;

/**

  • Created with IntelliJ IDEA.

  • Description: If you don’t work hard, you will a loser.

  • User: Listen-Y.

  • Date: 2020-08-04

  • Time: 20:40

*/

public class Demo2 {

public static void main(String[] args) throws InterruptedException {

AtomicInteger atomicInteger = new AtomicInteger();

Thread thread = new Thread() {

@Override

public void run() {

for (int i = 0; i < 5000; i++) {

atomicInteger.addAndGet(1);

}

}

};

Thread thread1 = new Thread() {

@Override

public void run() {

for (int i = 0; i < 5000; i++) {

atomicInteger.addAndGet(1);

}

}

};

thread.start();

thread1.start();

thread.join();

thread1.join();

System.out.println(atomicInteger.get());

}

}

/**

  • Created with IntelliJ IDEA.

  • Description: If you don’t work hard, you will a loser.

  • User: Listen-Y.

  • Date: 2020-08-04

  • Time: 20:53

*/

public class Demo3 {

private static int count = 0;

public static void main(String[] args) throws InterruptedException {

Thread thread = new Thread() {

@Override

public void run() {

for (int i = 0; i < 5000; i++) {

count++;

}

}

};

Thread thread1 = new Thread() {

@Override

public void run() {

for (int i = 0; i < 5000; i++) {

count++;

}

}

};

thread.start();

thread1.start();

thread.join();

thread1.join();

System.out.println(count);

}

}

CAS的缺陷 ABA问题
  • 这个问题就是加入现在有个num为0 有一个线程把他修改为1, 然后紧接着又有一个线程把他修改为0了 那此时仅仅通过CAS的比较是无法区分的

  • 解决这个问题就需要引入额外的信息 (给变量加一个版本号 每次进行修改 都递增版本号)

synchronize的原理

  • synchronize是java中的关键字,可以用来修饰实例方法、静态方法、还有代码块;主要有三种作用:可以确保原子性、可见性、有序性,原子性就是能够保证同一时刻有且只有一个线程在操作共享数据,其他线程必须等该线程处理完数据后才能进行;可见性就是当一个线程在修改共享数据时,其他线程能够看到,保证可见性,volatile关键字也有这个功能;有序性就是,被synchronize锁住后的线程相当于单线程,在单线程环境jvm的重排序是不会改变程序运行结果的,可以防止重排序对多线程的影响。

以synchronize为例学习锁优化

编辑器和JVM配合进行的

锁消除
  • 锁消除本质是以编辑器和JVM代码运行的情况智能的判断当前的锁有没有必要加 如果没有必要, 就会直接把锁干掉

/**

  • Created with IntelliJ IDEA.

  • Description: If you don’t work hard, you will a loser.

  • User: Listen-Y.

  • Date: 2020-08-04

  • Time: 21:21

*/

public class Demo4 {

public static void main(String[] args) {

StringBuffer buffer = new StringBuffer();

buffer.append(“listen”);

buffer.append(“listen”);

buffer.append(“listen”);

buffer.append(“listen”);

System.out.println(buffer);

}

}

在这里插入图片描述

  • 到库中我们可以发现StringBuffer是加锁线程安全的 但是在我们上面写的代码中完全不用考虑线程安全问题 所以在实际运行的时候就把锁消除了
偏向锁
  • 第一个尝试加锁的线程 不会真正的加锁 而是进入偏向锁(一种很轻量的锁) 知道其他线程也来竞争这把锁的时候 才会取消偏向锁的状态 真正的进行加锁

  • 这个很像我去球馆打球的时候借用人家球馆里的球的时候 当人多有人和我竞争的时候我就得去花钱租 人少的时候我就可以登记一下直接玩

  • 总而言之上述这俩个优化机制就是能不加锁就不加锁

自旋锁
  • 当有很多线程竞争锁的时候, 偏向锁状态被消除 此时没有得到锁的线程并不会直接直接挂起放弃 而是使用自旋锁 的方式来尝试去再次获取锁

  • 自旋锁能保证让其他想竞争锁的线程尽快得到锁 但是也相应付出了一定的cpu资源

  • 还是上面我去球馆打球的例子 如果此时就一个人来和我竞争这个篮球 我不会立马放弃 而是会稍微等会 看我是不是快回家了

  • 没有上锁就是无所状态, 在使用syn上锁的时候, 没有发生竞争就是偏向锁, 如果有少数线程发生了竞争就使用cas乐观乐观的自旋锁不断的在访问获取锁状态也就是轻量级锁,当线程访问到达十次还不能获得锁就会进入重量级锁

锁膨胀

最后

腾讯T3大牛总结的500页MySQL实战笔记意外爆火,P8看了直呼内行

腾讯T3大牛总结的500页MySQL实战笔记意外爆火,P8看了直呼内行

还是上面我去球馆打球的例子 如果此时就一个人来和我竞争这个篮球 我不会立马放弃 而是会稍微等会 看我是不是快回家了

  • 没有上锁就是无所状态, 在使用syn上锁的时候, 没有发生竞争就是偏向锁, 如果有少数线程发生了竞争就使用cas乐观乐观的自旋锁不断的在访问获取锁状态也就是轻量级锁,当线程访问到达十次还不能获得锁就会进入重量级锁
锁膨胀

最后

[外链图片转存中…(img-2BEQTMG4-1714330602517)]

[外链图片转存中…(img-gh9sLdNh-1714330602518)]

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值