Java多线程进阶(锁策略)

news2024/11/14 12:00:08

常见的锁策略:

1)悲观锁和乐观锁

加锁的时候,预测当前锁冲突的概率是大还是小。

预测当前锁冲突概率大,后续要做的工作往往就会更多,加锁开销就更大(时间,系统资源)=》悲观锁

预测当前锁冲突概率不大,后续要做的工作往往就更少,加锁开销就更小(时间,系统资源)=》乐观锁

synchronzied既是乐观锁,也是悲观锁

synchronzied支持自适应,能够自动的统计出当前的锁冲突的次数,进行判定当前锁冲突概率低还是概率高。

当冲突概率低的时候,就是按照乐观锁的方式来执行的。(速度更快)

当锁冲突概率高的时候,就会升级悲观锁的方式来执行(做的工作更多)

2)重量级锁和轻量级锁

一般来说,悲观锁,往往就是重量级锁,乐观锁就是轻量级锁。

3)自旋锁和挂起等待锁

自旋锁,是轻量级锁的一种典型的实现方式

消耗了更多的cpu资源,但是一旦锁被释放,就能第一时间拿到锁。拿到锁的速度很快。消耗cpu

挂起等待锁,是重量级锁的一种典型实现方式。

借助系统中的线程,当尝试加锁,并且锁被占用了,出现锁冲突,就会让当前这个尝试加锁的线程,被挂起(阻塞状态)此时这个线程就不会参与调度了。

直到这个线程被释放了,然后系统才能唤醒这个线程,去尝试重新获取锁。

(拿到锁的速度更慢,节省cpu)

synchronzied 轻量级锁部分,基于自旋锁实现,重量级锁部分,基于挂起等待锁实现。(基于CAS机制来实现)

4)可重入锁和不可重入锁

synchronzied就是可重入锁,一个线程,针对这把锁,连续加锁两次,不会死锁。

比如c++de std::mutex就是不可重入锁,一个线程针对这把锁,连续加锁两次,会死锁。

5)公平锁和非公平锁

公平锁:严格按照先来后到的顺序来获取锁,哪个线程等待的时间长,哪个线程就拿到锁。

非公平锁:若干个线程,各凭本事,随机的获取到锁,和线程等待时间无关了。

synchronized属于非公平锁,多个线程,尝试获取这个锁,此时是按照概率均等的方式来进行获取的。

{系统本身线程调度的顺序就是随机的,如果需要实现公平锁,就需要引入额外的队列,按照加锁顺序把这些获取锁的线程的线程入队列,再一个一个的取}

6)互斥锁和读写锁

synchronized本事就是普通的互斥锁

读写锁,则是一个更特殊的锁(加读锁,加写锁,解锁)

Java的读写锁是这样设定的:

1)读锁和读锁之间,不会产生互斥

2)写锁和写锁之间,会产生互斥

3)读锁和写锁之间,会产生互斥

synchronized实现原理:

synchronized即使悲观锁也是乐观锁,既是轻量级锁也是重量级锁,轻量级锁是自旋转实现,重量级锁就是挂起等待锁实现,是可重入锁,不是读写锁,是非公平锁

synchronized的“自适应”

锁升级的过程:

1)未加锁的状态(无锁){代码中开始调用执行synchronized}

2)偏向锁

3)轻量级锁

4)重量级锁

偏向锁的过程:

首次使用synchronized对对象进行加锁的时候,不是真的加锁,而只是做一个“标记”(非常轻量,非常快,几乎没有开销)

如果没有别的线程尝试对这个对象加锁,就可以保持这个暧昧状态,一直到解锁。

但是,如果在偏向锁状态下,有某个线程也尝试来对这个对象加锁,立马把偏向锁升级成轻量级锁(真的加锁,真的有互斥了),相当于立即确认关系,也就可以保证锁能够正常生效。

本质上,偏向锁策略就是“懒”字具体体现,能不加锁,就不加锁,能晚加锁,就晚加锁。

针对一个锁对象来说,是不可逆的,只能升级,不能降级。

一旦升级到了重量级锁,不会回退到轻量级锁(当前jvm里面的做法)

7)锁消除,编译器优化策略

代码里面写了加锁操作,jvm会对当前的代码做出判定,看这个地方到底是不是真的需要加锁。

如果这个不需要加锁,就会自动的把加锁操作,给优化掉。

8)锁粗话,也是一种优化策略

有些逻辑中,需要频繁加锁频繁,编译器就会自动的把多次细粒度的锁,合并成一次粗粒度的锁。

三个简单的加锁操作,合并成一个加锁操作。

CAS compare and swap 比较和交换

这是一条cpu(原子的)指令,就可以完成比较和交换这样的一套操作下来。

CAS的流程==》想象成一个方法

  boolean cas(address,reg1,reg2){
            if(address ==reg1){}
            //把address内存地址的值和reg2寄存器的值进行交换
            return true;
        }
        return false;

这里说的交换,实际上更多的是来“赋值”,一般更关心内存中,交换后的数据。而不关心reg2寄存器里交换后的数据。

由于cpu提供了上述指令,因此操作系统内核,也就能够完成上述操作,就会提供出这样的CAS的api,jvm又对于系统的CASapi进一步的封装了,在Java代码中也就可以使用CAS操作了。

在Java中也有一些类,对cas进行了进一步的封装,典型的就是原子类。

Atomiclnteger相当于针对int进行了封装。可以保证此处的++--操作是原子的

package Thread;

import java.util.concurrent.atomic.AtomicInteger;

public class Demo25 {
    private static AtomicInteger count=new AtomicInteger(0);
    public static void main(String[] args) throws InterruptedException {
        Thread t=new Thread(() ->{
            for (int i = 0; i <10000 ; i++) {
                count.getAndIncrement();

            }

        });
        Thread t1=new Thread(() ->{
            for (int i = 0; i < 50000; i++) {
                count.getAndIncrement();
            }
        });
        t.start();
        t1.start();
        t.join();
        t1.join();
        System.out.println(count);
    }
}

CAS的ABA问题

CAS这里的核心是比较-发现相等-交换=》潜台词 发现相等=》数据中间没有发生过任何改变

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2239042.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

docker desktop运行rabittmq容器,控制台无法访问

docker desktop运行rabittmq容器&#xff0c;控制台无法访问 启动过程&#xff1a;…此处缺略&#xff0c;网上一大堆 原因 原因是在Docker上运行的RabbitMQ&#xff0c;默认情况下是没有启用管理插件和管理页面的 解决办法 使用命令 docker exec -it 容器id /bin/bash 进…

MySQL-事务(详细版)

目录 事务的含义 举一个例子 事务的特征&#xff08;面试高频&#xff09; 原子性 一致性 隔离性 持久性 事务结束 查看事务提交方式 查看事务提交的变量值&#xff1a;on 自动提交 off 不是自动提交 实例 事务回滚 验证事务回滚 事务实现&#xff1a;是数据库提…

Python “文件和IO操作” ——Python面试100道实战题目练习,巩固知识、检查技术、成功就业

本文主要是作为Python中“文件和IO操作”的一些题目&#xff0c;方便学习完Python的函数之后进行一些知识检验&#xff0c;感兴趣的小伙伴可以试一试&#xff0c;含选择题、判断题、填空题。 在做题之前可以先学习或者温习一下Python的异常处理机制&#xff0c;推荐阅读下面这篇…

【Docker】自定义网络:实现容器之间通过域名相互通讯

文章目录 一. 默认网络&#xff1a;docker0网络的问题二. 自定义网络三. nginx容器指之间通过主机名进行内部通讯四. redis集群容器&#xff08;跳过宿主机&#xff09;内部网络通讯1. 集群描述2. 基于bitnami镜像的环境变量快速构建redis集群 一. 默认网络&#xff1a;docker0…

Kafka-Eagle的配置——kafka可视化界面

通过百度网盘分享的文件&#xff1a;kafka-eagle-bin-2.0.8.tar.gz 链接&#xff1a;https://pan.baidu.com/s/1H3YONkL97uXbLTPMZHrfdg?pwdsltu 提取码&#xff1a;sltu 一、界面展示 二、软件配置 1、关闭kafka集群 kf.sh stop 2、将该软件上传到/opt/modules下 cd /opt…

计算机图形学论文 | 木工设计与制造计划的共同优化

&#x1f98c;&#x1f98c;&#x1f98c;读论文 我们的系统共同探索离散设计变量和制造计划的空间&#xff0c;以生成&#xff08;设计&#xff0c;制造计划&#xff09;对的帕累托前沿&#xff0c;使制造成本最小化。在该图中&#xff0c;(a)是椅子的输入设计和仅探索该设计的…

【百日算法计划】:每日一题,见证成长(023)

题目 每日温度 请根据每日气温列表,重新生成一个列表,对应的位置的输出为:要想观测到更高的气温,至少需要等待的天数.如果气温在这之后都不再升高,则该位置用0代替. 例如,给定一个列表[73, 74, 65, 80,] 你的输出应该是[1, 2, 1, 0] 思路 首先&#xff0c;我们先来画图分析一…

【在Linux世界中追寻伟大的One Piece】多路转接epoll

目录 1 -> I/O多路转接之poll 1.1 -> poll函数接口 1.2 -> poll的优点 1.3 -> poll的缺点 1.4 -> poll示例 1.4.1 -> 使用poll监控标准输入 2 -> I/O多路转接之epoll 2.1 -> 初识epoll 2.2 -> epoll的相关系统调用 2.2.1 -> epoll_cre…

推动AI云产业向深向实,云·AI·算力创新发展大会即将启幕

近年来&#xff0c;以AIGC为代表的新兴技术正加速演进&#xff0c;全球站在智能化变革的起点&#xff0c;人工智能与云计算的深度融合&#xff0c;也驱动云计算进入第三次发展浪潮&#xff0c;迎来前所未有的机遇。 伴随AI的快速发展&#xff0c;2024年《政府工作报告》明确提…

5G 现网信令参数学习(3) - RrcSetup(1)

目录 1. rlc-BearerToAddModList 1.1 rlc-Config 1.1.1 ul-AM-RLC 1.1.2 dl-AM-RLC 1.2 mac-LogicalChannelConfig 2. mac-CellGroupConfig 2.1 schedulingRequestConfig 2.2 bsr-Config 2.3 tag-Config 2.4 phr-Config 2.5 skipUplinkTxDynamic 3. physicalCellG…

【MyBatis源码】深入分析TypeHandler原理和源码

文章目录 原始 JDBC 存在的问题自定义 TypeHandler 实现TypeHandler详解BaseTypeHandler类TypeReference类型参考器43个类型处理器类型注册表&#xff1a;3个注解类枚举类 原始 JDBC 存在的问题 MyBatis 之所以设计了 TypeHandler&#xff08;类型处理器&#xff09;&#xff…

运营篇|公众号小程序如何实现流量主变现

公众号小程序如何实现流量主变现&#xff1f;三步走&#xff1a; ①开通流量主&#xff1b; ②接入广告&#xff1b; ③裂变传播&#xff1b; 一、小程序开通流量主的运营要求 微信小程序开通流量主的前提条件主要包括以下几个方面&#xff1a; 日活跃用户&#xff08;DAU…

丹摩征文活动 | 轻松上手图像生成:FLUX.1遇上ComfyUI,让复杂变简单!

一、背景 FLUX.1是由黑森林实验室推出的一款前沿图像生成模型&#xff0c;针对不同用户需求&#xff0c;提供了三种不同版本。 FLUX.1-pro是专为企业设计的闭源版本&#xff0c;拥有无与伦比的性能和生成能力。其在识别提示词、提升视觉质量、细节表现及输出多样性方面都有出…

PyTorch核心概念:从梯度、计算图到连续性的全面解析(三)

文章目录 Contiguous vs Non-Contiguous TensorTensor and ViewStrides非连续数据结构&#xff1a;Transpose( )在 PyTorch 中检查Contiguous and Non-Contiguous将不连续张量&#xff08;或视图&#xff09;转换为连续张量view() 和 reshape() 之间的区别总结 参考文献 Contig…

「IDE」集成开发环境专栏目录大纲

✨博客主页何曾参静谧的博客&#x1f4cc;文章专栏「IDE」集成开发环境&#x1f4da;全部专栏「Win」Windows程序设计「IDE」集成开发环境「UG/NX」BlockUI集合「C/C」C/C程序设计「DSA」数据结构与算法「UG/NX」NX二次开发「QT」QT5程序设计「File」数据文件格式「UG/NX」NX定…

Kafka经典面试题

1、kafka消息发送的流程&#xff1f; producer发送过程中启动两个线程 一个main线程 一个sender线程&#xff0c;在main线程中先创建一个双端队列&#xff08;RecordAccumlator、producerbatch&#xff09;&#xff0c;main将我们需要发送的东西经过拦截器&#xff0c;序列化&a…

手把手写深度学习(29):将DDP训练代码改成DeepSpeed

手把手写深度学习(0)&#xff1a;专栏文章导航 前言&#xff1a;deepspeed已经成为了大模型时代训练模型的常规武器&#xff0c;这篇博客以一个基于DDP的 Stable Diffusion模型训练为例&#xff0c;讲解如何从将DDP训练代码改成DeepSpeed。 目录 构建optimizer 构建scheduler…

信息收集系列(二):ASN分析及域名收集

内容预览 ≧∀≦ゞ 信息收集系列&#xff08;二&#xff09;&#xff1a;ASN分析及域名收集前言一、ASN 分析1. 获取 ASN 码2. 使用 ASNMap 获取 IP 范围3. 将 IP 范围转化为 IP 列表 二、关联域名收集1. 顶级域&#xff08;TLD&#xff09;收集测试方法 2. 根域名收集常用方法…

《数学分析》中不等式及补充

说明&#xff1a;此文章用于本人复习巩固&#xff0c;如果也能帮到大家那就更加有意义了。 注&#xff1a;1&#xff09;《数学分析》中的不等式及不等式的补充

HTML之图片和超链接的学习记录

图片 在HTML中&#xff0c;我们可以使用img标签来显示一张图片。对于img标签&#xff0c;我们只需要掌握它的三个属性&#xff1a;src、alt和title。 <img src"" alt"" title"" /> src用于指定图片所在的路径&#xff0c;这个路径可以是…