当前位置: 首页 > news >正文

JAVAEE——多线程进阶,锁策略

文章目录

  • 锁策略
    • 乐观锁和悲观锁
      • 乐观锁
      • 悲观锁
        • 两者的比较
    • 读写锁
    • 重量级锁和轻量级锁
      • 重量级锁
      • 轻量级锁
    • 自旋锁
    • 公平锁和非公平锁
      • 公平锁
      • 非公平锁
    • 可重入锁和不可重入锁
      • 可重入锁
      • 不可重入锁

锁策略

乐观锁和悲观锁

乐观锁

什么是乐观锁呢?我们可以认为乐观锁比较自信,当多线程执行的时候如果要对一个资源进行访问,那么乐观锁会认为这些线程的访问是不会造成冲突的,并且这些访问也不都是要进行修改。因此对这些线程访问更新的时候乐观锁才会进行检测查看这个进程的访问是否会造成冲突,如果会的话就返回错误信息由用户决定是否如何去做

悲观锁

悲观锁相较于乐观锁也是一种极端,悲观锁认为只要访问就一定会造成并发冲突,因此悲观锁认为只要是访问资源,都必须加上锁,这样当别人想要获取这个资源的时候就必须获取这把锁陷入了阻塞等待当中。

两者的比较

这里我们举一个例子来说明

假如说甲乙两位同学向老师请问问题,那么甲是一个悲观的人,乙是一个乐观的人,甲突然去找老师,老师肯定在忙碌无法给自己将题目,因此会先给老师发个消息询问老师是否在忙碌当得到老师的答复之后再决定是继续等待还是直接过去,而乙则是比较乐观,认为自己现在过去不会打扰到老师,老师可以立即解答自己的疑惑,因此乙就会直接过去询问老师问题,这时候可能老师确实没有忙碌可以直接解决问题也有可能老师是在忙碌的,这时候乙就需要进行等待了。


结论:两把锁各有特点针对于不同的场合使用不同的锁没有什么优劣性比较。

读写锁

读写锁。线程对一个资源的访问是分为读操作和写操作的,那么对于一个资源来说读操作是不会导致线程不安全的只有写操作才会导致线程不安全,因此线程对一个资源的访问加锁我们也可以分为读锁和写锁来进行,因此我们就需要搞明白哪些情况会导致线程不安全

  • 线程同时去读取一个数据:安全的
  • 一批线程去读另一批线程在写:不安全
  • 线程都在写:不安全

因此读写锁,也就诞生了,那么读写锁是怎么进行加锁的呢?按照字面意思肯定就是按照一个线程是读还是写来区别加锁了。那么既然是按照意图来进行区别加锁的我们首先当然要清除这个线程想要进行的操作是什么才可以来进行加锁。也就是加锁前需要获取这个线程的行为意图。
读写锁就是把读操作和写操作区分对待. Java 标准库提供了 ReentrantReadWriteLock 类, 实现了读写
锁.
我们来写一个示例代码运行一下查看

import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;public class Lock_policy  {public static  int tmp=10;public static final ReentrantReadWriteLock wrlock=new ReentrantReadWriteLock();public static void main(String[] args) {Thread t1=new Thread(()->{wrlock.readLock().lock();System.out.println("我是t1线程"+tmp);//wrlock.readLock().unlock();});Thread t2=new Thread(()->{wrlock.readLock().lock();System.out.println("我是t2线程"+tmp);//wrlock.readLock().unlock();});Thread t3=new Thread(()->{wrlock.writeLock().lock();tmp++;System.out.println("我是t3线程"+tmp);});t1.start();t2.start();}
}

首先我们可以观察到这个代码中我们创建的t3线程并没有start运行因此我们测试的是当两个线程同时加上读锁并且读一个数据的时候是否会阻塞我们看一下运行结果。
在这里插入图片描述
结果很明显程序正常跑完因此没有任何的阻塞。我们来试试把t3线程运行试试结果。

import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;public class Lock_policy  {public static  int tmp=10;public static final ReentrantReadWriteLock wrlock=new ReentrantReadWriteLock();public static void main(String[] args) {Thread t1=new Thread(()->{wrlock.readLock().lock();System.out.println("我是t1线程"+tmp);//wrlock.readLock().unlock();});Thread t2=new Thread(()->{wrlock.readLock().lock();System.out.println("我是t2线程"+tmp);//wrlock.readLock().unlock();});Thread t3=new Thread(()->{wrlock.writeLock().lock();tmp++;System.out.println("我是t3线程"+tmp);});t1.start();t2.start();t3.start();}
}

运行截图如下
在这里插入图片描述
那么是否只有这一种结果呢?当然不是。
在这里插入图片描述
在实验的过程中我们可能产生这些不同的结果那么这是为什么呢?原因很简单那就是因为t3线程在t1和t2线程获取读锁之前就已经加上了写锁导致了t1和t2的读操作阻塞了。那么无论上述的哪种 结果都是可以说明读写锁中读锁和写锁是阻塞的。

重量级锁和轻量级锁

重量级锁

在理解这里的时候我们要先搞明白什么是重量级锁。顾名思义听名字就感觉这个锁很慢,那么这种原因究竟是为什么呢?这就要追溯到锁的一个机制了。


我们要搞明白加锁是为了干什么?很简单加锁是为了保证我们的多个操作是原子性的。原子性的保证使得我们的操作避免了多线程的安全问题。那么为什么锁可以保证操作的原子性呢?其实说白了还是因为我们的硬件设备的支持也就是底层建筑决定上层建筑,因为我们的硬件支持,所以我们的操作系统可以给我们提供一系列的锁的操作接口,而操作系统提供的接口就是mutex。

  • CPU 提供了 “原子操作指令”.
  • 操作系统基于 CPU 的原子指令, 实现了 mutex 互斥锁.
  • JVM 基于操作系统提供的互斥锁, 实现了 synchronized 和 ReentrantLock 等关键字和类
    在这里插入图片描述

重量级锁:加锁机制非常依赖于OS提供的mutex因此在加锁的时候涉及到大量的从内核态到用户态的转变,效率较低。

轻量级锁

轻量级锁即加锁的时候尽量不依赖于mutex而是尽量在用户态代码完成. 实在搞不定了, 再使用 mutex。那么这时候有些美女或者帅哥可能就会很混乱,说的直白一些就是,轻量级锁就是尽量不去调用系统接口他就是一个优化。

自旋锁

什么是自旋锁呢?那么按照我们之前写的代码当我们的锁被抢占的时候如果我们也想抢占这把锁的话就需要先进行阻塞等待也就是wait然后等待被唤醒,可是我们不希望这样怎么办?也就是说可能当前占有锁的这个进程很快就结束了就要释放这把锁了

公平锁和非公平锁

公平锁

公平锁遵守先来后到的原则B比C先来的那么当A释放锁之后B就会比C先获取到释放的锁

非公平锁

不遵守先来后到的原则,synchronized()就是一个非公平锁,他的调度顺序是有操作系统决定的。

  • 操作系统内部的线程调度就可以视为是随机的. 如果不做任何额外的限制, 锁就是非公平锁. 如果要
    想实现公平锁, 就需要依赖额外的数据结构, 来记录线程们的先后顺序.
  • 公平锁和非公平锁没有好坏之分, 关键还是看适用场景.

可重入锁和不可重入锁

可重入锁

可重入的意思就是同一个线程可以多次获取同一把锁。也就是可以重新进入的锁。synchorinzed就是一把可重入锁。Java里只要以Reentrant开头命名的锁都是可重入锁,而且JDK提供的所有现成的Lock实现类,包括
synchronized关键字锁都是可重入的。

不可重入锁

不可重入锁就是当自己这个线程要重新申请这把锁的时候要进行等待便是不可重入锁。

相关文章:

JAVAEE——多线程进阶,锁策略

文章目录 锁策略乐观锁和悲观锁乐观锁悲观锁两者的比较 读写锁重量级锁和轻量级锁重量级锁轻量级锁 自旋锁公平锁和非公平锁公平锁非公平锁 可重入锁和不可重入锁可重入锁不可重入锁 锁策略 乐观锁和悲观锁 乐观锁 什么是乐观锁呢?我们可以认为乐观锁比较自信&am…...

富文本编辑器Quill全套教程

Quill简介 Quill是一款现代的富文本编辑器,它以其API驱动的设计和对文本格式的深度理解而著称。与传统的富文本编辑器不同,Quill专注于以字符为中心,构建了一个直观且易于使用的API,使得开发者能够轻松地对文本进行格式化和编辑。…...

Swift 代码注释的使用

Swift代码注释的使用 在 iOS 开发中,代码注释是一种很好的实践,可以帮助他人更容易理解你的代码。通常可以在代码中使用注释来解释代码的功能、目的、实现细节等。下面是一些常见的 iOS 代码注释示例: 1. 单行注释: // 这是一个…...

蓝桥杯—DS1302

目录 1.管脚 2.时序&官方提供的读写函数 3.如何使用读写函数 4.如何在数码管中显示在DS1302中读取出的数据? 1.管脚 2.时序&官方提供的读写函数 /* # DS1302代码片段说明1. 本文件夹中提供的驱动代码供参赛选手完成程序设计参考。2. 参赛选手可以自行…...

nginx: 集群环境配置搭建

nginx 集群环境搭建 1 ) 概述 nginx 本身就应该选择性能强劲的机器同时为了满足更多流量的需求, 多台nginx 机器做集群来满足强大的需求故而,我们需要一个负载均衡器,以及多台nginx的机器 这里负载均衡器应该有主从和热备,目前先使用一台来描…...

Linux:进程终止和等待

一、进程终止 main函数的返回值也叫做进程的退出码,一般0表示成功,非零表示失败。我们也可以用不同的数字来表示不同失败的原因。 echo $?//打印最近一次进程执行的退出码 而作为程序猿,我们更需要知道的是错误码所代表的错误信息&#x…...

一、next-auth 身份验证凭据-使用电子邮件和密码注册登录

一、next-auth 身份验证凭据-使用电子邮件和密码注册登录 文章目录 一、next-auth 身份验证凭据-使用电子邮件和密码注册登录一、前言二、前置准备1、环境配置2、相关库安装(1)vercel 配置(2)Yarn 包管理配置 3、next项目初始化与…...

2.SpringBoot利用Thymeleaf实现页面的展示

什么是Thymeleaf? Thymeleaf是一个现代服务器端Java模板引擎,适用于Web和独立环境,能够处理HTML,XML,JavaScript,CSS甚至纯文本。 Thymeleaf的主要目标是提供一种优雅且高度可维护的模板创建方式。为实现这…...

devtool: ‘source-map‘ 和 devtool: ‘#source-map‘的区别

devtool: ‘source-map’ 和 devtool: ‘#source-map’ 之间的区别主要在于前面的#字符。 从Webpack 4开始,就废弃了在devtool选项前加#的用法。 devtool: ‘source-map’ 选项意味着Webpack在构建过程中会生成独立的完整的source map文件。对于测试环境很有用&…...

Flutter Boost 3

社区的 issue 没有收敛的趋势。 设计过于复杂,概念太多。这让一个新手看 FlutterBoost 的代码很吃力。 这些问题促使我们重新梳理设计,为了彻底解决这些顽固的问题,我们做一次大升级,我们把这次升级命名为 FlutterBoost 3.0&am…...

ElementUI响应式Layout布局xs,sm,md,lg,xl

响应式布局 参照了 Bootstrap 的 响应式设计&#xff0c;预设了五个响应尺寸&#xff1a;xs、sm、md、lg 和 xl。 <el-row :gutter"10"><el-col :xs"8" :sm"6" :md"4" :lg"3" :xl"1"><div class…...

机器学习——典型的卷积神经网络

机器学习——典型的卷积神经网络 卷积神经网络&#xff08;Convolutional Neural Networks&#xff0c;CNNs&#xff09;是一类在图像处理领域应用广泛的深度学习模型。它通过卷积操作和池化操作来提取图像的特征&#xff0c;并通过全连接层来进行分类或回归任务。在本文中&am…...

速通数据结构与算法第四站 双链表

系列文章目录 速通数据结构与算法系列 1 速通数据结构与算法第一站 复杂度 http://t.csdnimg.cn/sxEGF 2 速通数据结构与算法第二站 顺序表 http://t.csdnimg.cn/WVyDb 3 速通数据结构与算法第三站 单链表 http://t.csdnimg.cn/cDpcC 感谢佬们…...

51单片机学习笔记12 SPI接口 使用1302时钟

51单片机学习笔记12 SPI接口 使用1302时钟 一、DS1302简介1. 功能特性2. 涓流充电3. 接口介绍时钟数据和控制线&#xff1a;电源线&#xff1a;备用电池连接&#xff1a; 二、寄存器介绍1. 控制寄存器2. 时间寄存器3. 日历/时钟寄存器 三、BCD码介绍四、DS1302时序1. 读时序2. …...

php编辑器 ide 主流编辑器的优缺点。phpstorm vscode atom 三者对比

编辑器PhpStormvscodeAtom是否收费收费&#xff0c;有30天试用期免费免费内存占用Java平台&#xff0c;一个进程1G多内存占用好几个进程&#xff0c;合起来1G上下/基本功能都具备&#xff0c;有的功能需要装插件都具备&#xff0c;有的功能需要装插件都具备&#xff0c;有的功能…...

【动手学深度学习】深入浅出深度学习之RMSProp算法的设计与实现

目录 &#x1f31e;一、实验目的 &#x1f31e;二、实验准备 &#x1f31e;三、实验内容 &#x1f33c;1. 认识RMSProp算法 &#x1f33c;2. 在optimizer_compare_naive.py中加入RMSProp &#x1f33c;3. 在optimizer_compare_mnist.py中加入RMSProp &#x1f33c;4. 问…...

大转盘抽奖小程序源码

源码介绍 大转盘抽奖小程序源码&#xff0c;测试依旧可用&#xff0c;无BUG&#xff0c;跑马灯旋转效果&#xff0c;非常酷炫。 小程序核心代码参考 //index.js //获取应用实例 var app getApp() Page({data: {circleList: [],//圆点数组awardList: [],//奖品数组colorCirc…...

数据结构(无图版)

数据结构与算法&#xff08;无图版&#xff0c;C语言实现&#xff09; 1、绪论 1.1、数据结构的研究内容 一般应用步骤&#xff1a;分析问题&#xff0c;提取操作对象&#xff0c;分析操作对象之间的关系&#xff0c;建立数学模型。 1.2、基本概念和术语 数据&#xff1a;…...

软件测试中的顶级测试覆盖率技术

根据 CISQ 报告&#xff0c;劣质软件每年给美国公司造成约2.08 万亿美元的损失。虽然软件工具是企业和行业领域的必需品&#xff0c;但它们也容易出现严重错误和性能问题。人类手动测试不再足以检测和消除软件错误。 因此&#xff0c;产品或软件开发公司必须转向自动化测试&am…...

vscode使用技巧

常用快捷键 代码格式 Windows系统。格式化代码的快捷键是“ShiftAltF” Mac系统。格式化代码的快捷键是“ShiftOptionF” Ubuntu系统。格式化代码的快捷键是“CtrlShiftI”配置缩进 点击左上角的“文件”菜单&#xff0c;然后选择“首选项”>“设置”&#xff0c;或者使用…...

mongodb源码分析session执行handleRequest命令find过程

mongo/transport/service_state_machine.cpp已经分析startSession创建ASIOSession过程&#xff0c;并且验证connection是否超过限制ASIOSession和connection是循环接受客户端命令&#xff0c;把数据流转换成Message&#xff0c;状态转变流程是&#xff1a;State::Created 》 St…...

前端导出带有合并单元格的列表

// 导出async function exportExcel(fileName "共识调整.xlsx") {// 所有数据const exportData await getAllMainData();// 表头内容let fitstTitleList [];const secondTitleList [];allColumns.value.forEach(column > {if (!column.children) {fitstTitleL…...

django filter 统计数量 按属性去重

在Django中&#xff0c;如果你想要根据某个属性对查询集进行去重并统计数量&#xff0c;你可以使用values()方法配合annotate()方法来实现。这里有两种常见的方法来完成这个需求&#xff1a; 方法1&#xff1a;使用annotate()和Count 假设你有一个模型Item&#xff0c;并且你想…...

前端开发面试题总结-JavaScript篇(一)

文章目录 JavaScript高频问答一、作用域与闭包1.什么是闭包&#xff08;Closure&#xff09;&#xff1f;闭包有什么应用场景和潜在问题&#xff1f;2.解释 JavaScript 的作用域链&#xff08;Scope Chain&#xff09; 二、原型与继承3.原型链是什么&#xff1f;如何实现继承&a…...

AI编程--插件对比分析:CodeRider、GitHub Copilot及其他

AI编程插件对比分析&#xff1a;CodeRider、GitHub Copilot及其他 随着人工智能技术的快速发展&#xff0c;AI编程插件已成为提升开发者生产力的重要工具。CodeRider和GitHub Copilot作为市场上的领先者&#xff0c;分别以其独特的特性和生态系统吸引了大量开发者。本文将从功…...

项目部署到Linux上时遇到的错误(Redis,MySQL,无法正确连接,地址占用问题)

Redis无法正确连接 在运行jar包时出现了这样的错误 查询得知问题核心在于Redis连接失败&#xff0c;具体原因是客户端发送了密码认证请求&#xff0c;但Redis服务器未设置密码 1.为Redis设置密码&#xff08;匹配客户端配置&#xff09; 步骤&#xff1a; 1&#xff09;.修…...

USB Over IP专用硬件的5个特点

USB over IP技术通过将USB协议数据封装在标准TCP/IP网络数据包中&#xff0c;从根本上改变了USB连接。这允许客户端通过局域网或广域网远程访问和控制物理连接到服务器的USB设备&#xff08;如专用硬件设备&#xff09;&#xff0c;从而消除了直接物理连接的需要。USB over IP的…...

Go 并发编程基础:通道(Channel)的使用

在 Go 中&#xff0c;Channel 是 Goroutine 之间通信的核心机制。它提供了一个线程安全的通信方式&#xff0c;用于在多个 Goroutine 之间传递数据&#xff0c;从而实现高效的并发编程。 本章将介绍 Channel 的基本概念、用法、缓冲、关闭机制以及 select 的使用。 一、Channel…...

iview框架主题色的应用

1.下载 less要使用3.0.0以下的版本 npm install less2.7.3 npm install less-loader4.0.52./src/config/theme.js文件 module.exports {yellow: {theme-color: #FDCE04},blue: {theme-color: #547CE7} }在sass中使用theme配置的颜色主题&#xff0c;无需引入&#xff0c;直接可…...

多模态图像修复系统:基于深度学习的图片修复实现

多模态图像修复系统:基于深度学习的图片修复实现 1. 系统概述 本系统使用多模态大模型(Stable Diffusion Inpainting)实现图像修复功能,结合文本描述和图片输入,对指定区域进行内容修复。系统包含完整的数据处理、模型训练、推理部署流程。 import torch import numpy …...