JUC并发编程——各种锁的理解(基于狂神说的学习笔记)

各种锁的理解

公平锁与非公平锁

公平锁:非常公平,不能够插队,先来后到

非公平锁:可以插队,比较灵活(默认都是非公平,如:synchronized,lock)

// Lock lock = new ReentrantLock(); 不带参数的构造方法
public ReentrantLock() {sync = new NonfairSync();
}
// Lock lock = new ReentrantLock(true); 带参数的构造方法   
public ReentrantLock(boolean fair) {sync = fair ? new FairSync() : new NonfairSync();
}

可重入锁(递归锁)

当一个锁中还有一个锁时,线程不会放弃第一把锁,就像递归一样层层深入,一直持有锁。

可以类比成:当你拿到进入一个房子的锁,进入房子后,再拿到进入卧室的锁,进入卧室,此时,就算你已经拿到了卧室的锁,你也并没有放弃房子的锁,别人依然进不来房子。

synchronized版

package lock;// Synchronized
public class Demo01 {public static void main(String[] args) {phone phone = new phone();new Thread(()->{phone.sms();},"A").start();new Thread(()->{phone.sms();},"B").start();}
}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");}
}

lock 版

package lock;import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;public class Demo02 {public static void main(String[] args) {phone2 phone2 = new phone2();new Thread(()->{phone2.sms();},"A").start();new Thread(()->{phone2.sms();},"B").start();}
}class phone2{Lock lock = new ReentrantLock();public void sms(){lock.lock();try {System.out.println(Thread.currentThread().getName()+"sms");call();// 这里也有锁} catch (Exception e) {throw new RuntimeException(e);} finally {lock.unlock();}}public void call(){lock.lock();// 锁必须配对,否则会死锁try {System.out.println(Thread.currentThread().getName()+"call");} catch (Exception e) {throw new RuntimeException(e);} finally {lock.unlock();}}
}

运行结果如下:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

从结果可以看到,即使A线程进入了call方法,也依然没有放弃sms方法的锁,B线程依然无法进入sms方法

自旋锁

一个自旋锁的源代码示例

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;
}

自旋锁示例:

设计一个自旋锁:

package lock;import java.util.concurrent.atomic.AtomicReference;/*** 自旋锁*/
public class Demo03 {AtomicReference<Thread> atomicReference = new AtomicReference<>();// 加锁public void myLock(){Thread thread = Thread.currentThread();System.out.println(Thread.currentThread().getName()+"-->my lock");while(!atomicReference.compareAndSet(null,thread)){}System.out.println(Thread.currentThread().getName()+"--->has this lock");}// 解锁public void myUnlock(){Thread thread = Thread.currentThread();System.out.println(Thread.currentThread().getName()+"-->my unlock");atomicReference.compareAndSet(thread,null);}
}

该自旋锁示例本质上使用了CAS操作,笔者在狂神说代码上加入了

System.out.println(Thread.currentThread().getName()+"--->has this lock");

测试类:

package lock;import java.util.concurrent.TimeUnit;public class TestDemo03 {public static void main(String[] args) throws InterruptedException {// 底层使用的是CASDemo03 lock = new Demo03();new Thread(()->{lock.myLock();try {TimeUnit.SECONDS.sleep(2);} catch (Exception e) {throw new RuntimeException(e);} finally {lock.myUnlock();}},"T1").start();TimeUnit.SECONDS.sleep(1);new Thread(()->{lock.myLock();try {TimeUnit.SECONDS.sleep(2);} catch (Exception e) {throw new RuntimeException(e);} finally {lock.myUnlock();}},"T2").start();}}

结果如下:

在这里插入图片描述

至此,读者可以看到,T1在打印“has this lock”之后,T2是无法持有该锁,它在不断地自旋,即进入while循环一直判断,我们来看一下这个代码在做什么

while(!atomicReference.compareAndSet(null,thread))

这条代码是actomicReference调用了一个compareAndSet方法(CAS),这个方法是用来判断,如果Thread为Null,则加入修改为thread,并返回true,!true == false,则会退出while循环,如果Thread为某个线程thread,则于CAS的预期值(null)不同,会返回false,!false == true,所以会进入循环,循环体内什么都没有,又会进入判断,周而复始,直到那个线程unlock,调用CAS将thread修改为null。

思考:为什么要让锁一直自旋判断呢?

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

学习c#桌面应用编程 --- 我的第一个游戏

场景 我需要做一个c#桌面窗口软件&#xff0c;但是我曾经都是专职于java开发&#xff0c;但是java对windows并不是特别友好(awt除外)&#xff0c;于是必须需要掌握c#桌面编程&#xff0c;所以我需要手动做一个小游戏&#xff0c;来学习c#的一些基本桌面应用的知识。 开始 这…

Leetcode 剑指 Offer II 049. 求根节点到叶节点数字之和

题目难度: 中等 原题链接 今天继续更新 Leetcode 的剑指 Offer&#xff08;专项突击版&#xff09;系列, 大家在公众号 算法精选 里回复 剑指offer2 就能看到该系列当前连载的所有文章了, 记得关注哦~ 题目描述 给定一个二叉树的根节点 root &#xff0c;树中每个节点都存放有…

vue3后台管理系统之路由守卫

下载进度条 pnpm install nprogress //路由鉴权:鉴权,项目当中路由能不能被的权限的设置(某一个路由什么条件下可以访问、什么条件下不可以访问) import router from /router import setting from ./setting // eslint-disable-next-line typescript-eslint/ban-ts-comment /…

FreeRTOS入门教程(事件组概念和函数使用)

文章目录 前言一、事件组概念二、事件组和信号量&#xff0c;队列的区别三、事件组相关函数三、事件组应用示例1.等待多个事件2.任务同步 总结 前言 本篇文章将带大家学习什么是事件组以及如何使用事件组。 一、事件组概念 事件组通常是由一组位&#xff08;bits&#xff09…

Linux下的命令行参数和环境变量

命令行参数 什么是命令行参数 命令行参数是指在执行命令行程序时&#xff0c;给程序传递的额外参数。在Linux终端中&#xff0c;命令行参数通常通过在命令后面添加空格分隔的参数来传递。 Linux下以main函数举例说明 #include<stdio.h>int main(int argc char* argv[])…

Java:ApacheHttpClient连接寿命(timeToLive)未配置问题分析

一、问题描述 若 Apache HttpClient 未设置 timeToLive&#xff0c;通过服务域名访问服务的实例并且服务域名解析出的 IP 发生变化时&#xff0c;在短时间内会有部分请求出现连接异常错误。 二、问题分析 Apache HttpClient 通过服务域名从连接池获取连接&#xff0c;当连接…

[C语言]排序的大乱炖——喵喵的成长记

宝子&#xff0c;你不点个赞吗&#xff1f;不评个论吗&#xff1f;不收个藏吗&#xff1f; 最后的最后&#xff0c;关注我&#xff0c;关注我&#xff0c;关注我&#xff0c;你会看到更多有趣的博客哦&#xff01;&#xff01;&#xff01; 喵喵喵&#xff0c;你对我真的很重要…

睿趣科技:抖音小店新手运营攻略

随着短视频平台的兴起&#xff0c;抖音已经成为了一个炙手可热的营销工具。越来越多的商家选择在抖音上开设小店&#xff0c;以此来拓展自己的业务。那么&#xff0c;作为新手&#xff0c;如何运营好自己的抖音小店呢?本文将为您提供一些实用的建议。 首先&#xff0c;要明确自…

如何创建高效的 Python Docker 镜像详解

Docker是打包和部署容器中应用程序的行业标准软件。Docker镜像是构建和运行应用程序的基础&#xff0c;为了充分发挥Docker的潜力&#xff0c;您需要优化镜像以提高资源效率、安全性和性能。这将确保您的应用程序在Docker生态系统内无缝运行。 通过一个实际示例来学习如何实现…

Oracle监听服务启动后停止

问题 解决办法 找到listener.ora文件,箭头指的地方&#xff0c;host改为localhost 如何找到listener.ora 其中1522端口&#xff0c;是我新增的监听服务。之前这个host是一个固定的ip地址&#xff0c;我更换网络环境后&#xff0c;ip地址变了&#xff0c;所以导致监听启动失败。…

ChatGPT(1):ChatGPT初识

1 ChatGPT原理 ChatGPT 是基于 GPT-3.5 架构的一个大型语言模型&#xff0c;它的工作原理涵盖了深度学习和自然语言处理技术。以下是 ChatGPT 的工作原理的一些关键要点&#xff1a; 神经网络架构&#xff1a;ChatGPT 的核心是一个深度神经网络&#xff0c;采用了变种的 Tran…

vue-pdf多页预览异常,Rendering cancelled, page 1 Error at BaseExceptionClosure xxx

项目开发使用vue-pdf,单页情况预览正常&#xff0c;多页vue-pdf预览异常&#xff0c;第一次预览时&#xff0c;会先弹出异常模态窗口&#xff0c;关闭模态窗口&#xff0c;pdf又是正常显示&#xff0c;报错信息及异常截图如下&#xff1a; 报错信息 Rendering cancelled, page…

Nginx集群负载均衡配置完整流程

今天&#xff0c;良哥带你来做一个nginx集群的负载均衡配置的完整流程。 一、准备工作 本次搭建的操作系统环境是win11&#xff0c;linux可配置类同。 1&#xff09;首先&#xff0c;下载nginx。 下载地址为&#xff1a;http://nginx.org/en/download.html 良哥下载的是&am…

vulkan SDK安装

文章目录 一. vulcan官网二.安装流程 一. vulcan官网 https://vulkan.lunarg.com/sdk/home#windows 二.安装流程 点击下载 双击下载的*.exe进行安装 点击下一步 点击下一步 选择安装位置&#xff0c;点击下一步 点击全选&#xff0c;选择下一步 勾选同意&#xf…

2023年中国多功能折叠刀产量、销量及市场规模分析[图]

多功能折叠刀是一种集多种功能于一身的刀具&#xff0c;通常包括切割、开瓶、剥皮、锯木等功能&#xff0c;可以通过折叠和展开的方式来实现不同的功能&#xff0c;具有便携、多用途、安全等特点&#xff0c;广泛应用于户外探险、露营、自驾旅行等场景。 多功能折叠刀行业分类…

grafana v10.1版本设置告警

1. 相关概念概述 如图所示&#xff0c;点击切换菜单标志&#xff0c;可以看到警报相关子选项。 警报规则&#xff1a;通过PromQL语句定义告警规则&#xff0c;即达到怎样的状态触发告警。 联络点&#xff1a; 设置当警报规则实例触发时&#xff0c;如何通知联系人&#xff0c;…

使用Perl和WWW::Mechanize库编写

以下是一个使用Perl和WWW::Mechanize库编写的网络爬虫程序的内容。代码必须使用以下代码&#xff1a;jshk.com.cn/get_proxy 首先&#xff0c;确保已经安装了Perl和WWW::Mechanize库。如果没有&#xff0c;请使用以下命令安装&#xff1a; cpan WWW::Mechanize创建一个新的Pe…

代码随想录二刷 Day 44

01背包问题二维做法先遍历背包或者物品都可以&#xff0c;然后是前序遍历&#xff1b; 一维做法一定先遍历物品然后遍历背包&#xff0c;遍历背包的时候是后序遍历&#xff1b;一维做法还是有点难理解&#xff0c;其实就是后面的数字还是要从前面的推导出来&#xff0c;但是如…

安装Apache2.4

二、安装配置Apache&#xff1a; 中文官网&#xff1a;Apache 中文网 官网 (p2hp.com) 我下的是图中那个版本&#xff0c;最新的64位 下载下后解压缩。如解压到D:\tool\Apache24 PS&#xff1a;特别要注意使用的场景和64位还是32位版本 2、修改Apcahe配置文件 2.1配置Apache…

【音视频流媒体】 3、ffmpeg、ffplay、ffprobe 超详细介绍

文章目录 一、ffmpeg1.1 安装1.2 基本参数 二、ffprobe2.1 查编码格式2.2 查视频时长 五、视频转流5.1 MP4转H2645.2 H264转MP45.3 AVI转MP45.4 MP4转H265 六、视频文件6.1 播放6.2 filter 过滤器6.2.1 crop 6.3 视频截取6.4 视频拼接6.5 获取分辨率 七、视频和图7.1 视频抽帧7…