锁( ReentrantLock,Synchronized)

1.lock和synchronized

  • 语法层面

synchronized 是关键字,源码在 jvm 中,用 c++ 语言实现;

Lock 是接口,源码由 jdk 提供,用 java 语言实现;

使用 synchronized 时,退出同步代码块锁会自动释放,而使用 Lock 时,需要手动调用 unlock 方法释放锁

  • 功能层面

二者均属于悲观锁、都具备基本的互斥、同步、锁重入功能;

Lock 提供了许多 synchronized 不具备的功能,例如公平锁、可打断、可超时、多条件变量

Lock 有适合不同场景的实现,如 ReentrantLock, ReentrantReadWriteLock(读写锁)

  • 性能层面

在没有竞争时,synchronized 做了很多优化,如偏向锁、轻量级锁,性能不赖

在竞争激烈时,Lock 的实现通常会提供更好的性能

2.ReentrantLock的代码实现

对于ReentrantLock来说,它既可以使用乐观锁思想,也可以使用悲观锁思想,具体取决于如何使用它的不同方法。

  1. 悲观锁思想: 在使用ReentrantLock时,可以使用它的lock()和unlock()方法来实现悲观锁思想。在使用lock()方法获取锁之前,它会一直等待直到获取到锁,如果其他线程已经持有锁,则当前线程会被阻塞。这种方式与传统的悲观锁思想相似,它假设并发访问会导致冲突,因此在访问共享资源之前先获取锁。

示例代码:

ReentrantLock lock = new ReentrantLock();
​
lock.lock(); // 获取锁
try {// 访问共享资源
} finally {lock.unlock(); // 释放锁
}
  1. 乐观锁思想: 在使用ReentrantLock时,可以使用它的tryLock()方法来实现乐观锁思想。tryLock()方法尝试获取锁,如果获取成功则返回true,否则返回false,不会一直等待。这种方式与乐观锁思想相似,它假设并发访问不会导致冲突,因此直接进行操作而不获取锁。

示例代码:

ReentrantLock lock = new ReentrantLock();
​
if (lock.tryLock()) { // 尝试获取锁try {// 访问共享资源} finally {lock.unlock(); // 释放锁}
} else {// 锁被其他线程持有,处理逻辑
}

需要注意的是,ReentrantLock的乐观锁思想并不是基于CAS机制实现的,而是基于AQS(AbstractQueuedSynchronizer)实现的。因此,它的乐观锁并不是真正意义上的无锁操作,而是一种基于线程等待/唤醒机制的乐观策略。

3.ReentrantLock构造原理

ReentrantLock主要利用CAS+AQS队列来实现。它支持公平锁和非公平锁,两者的实现类似

构造方法接受一个可选的公平参数(默认非公平锁),当设置为true时,表示公平锁,否则为非公平锁。公平锁的效率往往没有非公平锁的效率高,在许多线程访问的情况下,公平锁表现出较低的吞吐量。

拓展延申

1)AQS

关键时FIFO双向队列和属性state

  • 是多线程中的队列同步器。是一种锁机制,它是做为一个基础框架使用的,像ReentrantLock、Semaphore都是基于AQS实现的

  • AQS内部维护了一个先进先出的双向队列,队列中存储的排队的线程

  • 在AQS内部还有一个属性state,这个state就相当于是一个资源,默认是0(无锁状态),如果队列中的有一个线程修改成功了state为1,则当前线程就相等于获取了资源

  • 在对state修改的时候使用的cas操作,保证多个线程修改的情况下原子性

2)了解AQS与Synchronized的区别

3)CAS

CAS的全称是: Compare And Swap(比较再交换),它体现的一种乐观锁的思想,在无锁情况下保证线程操作共享数据的原子性。

4)乐观锁与悲观锁

CAS 是基于乐观锁的思想:最乐观的估计,不怕别的线程来修改共享变量,就算改了也没关系,我吃亏点再重试呗。

synchronized 是基于悲观锁的思想:最悲观的估计,得防着其它线程来修改共享变量,我上了锁你们都别想改,我改完了解开锁,你们才有机会。

在Java中,synchronized关键字ReentrantLock类都是悲观锁的实现。

在Java中,Atomic类和CAS(Compare and Swap)机制都是乐观锁的实现。

4.Java中synchronized的代码实例

下面是Java中使用synchronized关键字的几种代码示例:

  1. 同步方法:

public synchronized void synchronizedMethod() {// 同步的代码块
}
  1. 同步代码块:

public void synchronizedBlock() {synchronized (this) {// 同步的代码块}
}
  1. 静态同步方法:

public static synchronized void synchronizedStaticMethod() {// 同步的代码块
}
  1. 同步对象锁:

public class MyClass {private final Object lock = new Object();
​public void synchronizedObjectLock() {synchronized (lock) {// 同步的代码块}}
}

在上述示例中,使用synchronized关键字修饰的方法或代码块被称为同步方法或同步代码块,它们保证了同一时刻只能有一个线程访问被同步的代码块。synchronized关键字可以修饰方法、代码块、静态方法,以及指定的对象锁。

当一个线程进入到一个被synchronized修饰的方法或代码块时,它会尝试获取对象的锁。如果锁没有被其他线程占用,则该线程获取到锁并执行同步代码块;如果锁已经被其他线程占用,则该线程会进入阻塞状态,直到锁被释放。

需要注意的是,synchronized关键字是可重入的,即一个线程可以多次获取同一个锁。当一个线程已经获取到锁时,它可以再次进入被同步修饰的方法或代码块,而不会被阻塞。这种机制可以避免死锁的发生。

另外,synchronized关键字还可以用于实现线程之间的通信,通过wait()、notify()和notifyAll()方法来实现线程的等待和唤醒操作。这些方法必须在synchronized修饰的代码块中调用,并且是针对同一个对象锁的操作。

5.说一下无锁操作?

无锁操作是指在并发编程中,通过使用特定的算法和数据结构,避免使用传统的锁机制(如互斥锁、读写锁等),从而实现对共享资源的并发访问而无需阻塞或等待其他线程释放锁的操作。

无锁操作通常基于原子操作和CAS(Compare and Swap)机制来实现。CAS是一种乐观锁思想的实现方式,它通过比较内存中的值与期望值,如果相等则更新为新值,否则不做任何操作。CAS操作是原子性的,可以保证在多线程环境下的一致性。

无锁操作的优点包括:

  1. 减少线程的阻塞和切换开销:无锁操作不需要等待其他线程释放锁,避免了线程的阻塞和切换开销,提高了系统的并发性能。

  2. 避免死锁和饥饿问题:无锁操作不涉及锁的竞争和资源的争夺,可以避免死锁和饥饿问题。

  3. 提高系统的可伸缩性:无锁操作可以实现更细粒度的并发控制,提高系统的可伸缩性。

然而,无锁操作也存在一些挑战和限制:

  1. 实现复杂度高:无锁操作需要使用特定的算法和数据结构,实现起来较为复杂。

  2. 适用场景有限:无锁操作适用于对共享资源的读操作频繁,写操作较少的场景,对于复杂的写操作,仍然需要使用锁来保证操作的原子性

  3. ABA问题:由于无锁操作不需要获取锁,可能会导致ABA问题,即一个值被修改为另一个值,然后再被修改回原来的值,导致线程无法察觉到值的变化。

总之,无锁操作是一种高效的并发编程方式,可以提高系统的并发性能和可伸缩性,但需要根据具体场景和需求来选择合适的并发控制策略。

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

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

相关文章

Axure RP PC电商平台Web端交互原型模板

Axure RP PC电商平台Web端交互原型模板。原型图内容齐全,包含了用户中心、会员中心、优惠券、积分、互动社区、运营推广、内容推荐、商品展示、订单流程、订单管理、售后及服务等完整的电商体系功能架构和业务流程。 在设计尺寸方面,本套模板按照主流的…

MybatisPlus 核心功能 条件构造器 自定义SQL Service接口 静态工具

MybatisPlus 快速入门 常见注解 配置_软工菜鸡的博客-CSDN博客 2.核心功能 刚才的案例中都是以id为条件的简单CRUD,一些复杂条件的SQL语句就要用到一些更高级的功能了。 2.1.条件构造器 除了新增以外,修改、删除、查询的SQL语句都需要指定where条件。因此…

12. 微积分 - 梯度积分

Hi,大家好。我是茶桁。 上一节课,我们讲了方向导数,并且在最后留了个小尾巴,是什么呢?就是梯度。 我们再来回看一下但是的这个式子: [ f x f y

打造西南交通感知新范式,闪马智能携手首讯科技落地创新中心

9月4日,2023年中国国际智能产业博览会(以下简称“智博会”)在重庆拉开帷幕。大会期间,由上海闪马智能科技有限公司(以下简称“闪马智能”)与重庆首讯科技股份有限公司(以下简称“首讯科技”&…

Logback日志记录只在控制台输出sql,未写入日志文件【解决】

原因:持久层框架对于Log接口实现方式不一样,日记记录的位置及展示方式也也不一样 mybatis-plus:configuration:log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # sql只会打印到控制台不会输出到日志文件种mybatis-plus:configuration:log-impl…

前后端项目部署上线详细笔记

部署 参考文章:如何部署网站?来比比谁的方法多 - 哔哩哔哩大家好,我是鱼皮,不知道朋友们有没有试着部署过自己开发的网站呢?其实部署网站非常简单,而且有非常多的花样。这篇文章就给大家分享几种主流的前端…

DVWA失效的访问控制

失效的访问控制,可以认为是系统对一些功能进行了访问或权限限制,但因为种种原因,限制并没有生效,造成失效的访问控制漏洞,比如越权等 这里以DVWA为例,先访问低难度的命令执行并抓包 删除cookie,并在请求头…

从0到1学会Git(第二部分):Git的本地操作和管理

写在前面:本文介绍了在本地仓库进行文件的处理以及本地的合并等操作。 前置知识:文件可以处在三个区域,分别为工作区,暂存区和本地仓库,我们此文的目标即是将文件存储在本地仓库中。我们可以将文件的区域理解为,cpu中&#xff0c…

UDP和TCP协议报文格式详解

在初识网络原理(初识网络原理_蜡笔小心眼子!的博客-CSDN博客)这篇博客中,我们简单的了解了一下TCP/IP五层网络模型,这篇博客将详细的学习一下五层网络模型中传输层的两个著名协议:UDP和TCP 目录 一, 传输层的作用 二, UDP 1,UDP协议的特点 2,UDP报文格式 三, TC…

Python爬取天气数据并进行分析与预测

随着全球气候的不断变化,对于天气数据的获取、分析和预测显得越来越重要。本文将介绍如何使用Python编写一个简单而强大的天气数据爬虫,并结合相关库实现对历史和当前天气数据进行分析以及未来趋势预测。 1 、数据源选择 选择可靠丰富的公开API或网站作…

视频监控/视频汇聚/视频云存储EasyCVR平台接入华为ivs3800平台提示400报错,该如何解决?

开源EasyDarwin视频监控TSINGSEE青犀视频平台EasyCVR能在复杂的网络环境中,将分散的各类视频资源进行统一汇聚、整合、集中管理,在视频监控播放上,视频云存储/安防监控汇聚平台可支持1、4、9、16个画面窗口播放,可同时播放多路视频…

垃圾回收 - 复制算法

GC复制算法是Marvin L.Minsky在1963年研究出来的算法。说简单点,就是只把某个空间的活动对象复制到其它空间,把原空间里的所有对象都回收掉。这是一个大胆的想法。在此,我们将复制活动对象的原空间称为From空间,将粘贴活动对象的新…

Flink---1、概述、快速上手

1、Flink概述 1.1 Flink是什么 Flink的官网主页地址:https://flink.apache.org/ Flink的核心目标是“数据流上有状态的计算”(Stateful Computations over Data Streams)。 具体说明:Apache Flink是一个“框架和分布式处理引擎”,用于对无界…

面试总结 - 计算机网络

计算机网络 1 OSI 七层模型 | TCP与UDP | 响应状态码 OSI 模型 应用层: 计算机用户,以及各种应用程序和网络之间的接口,其功能是直接向用户提供服务,完成用户希望在网络上完成的各种工作。 HTTP SMTP FTP DNS 表示层: 负责数据格式的转换&…

算法笔记:二叉树

1 基本二叉树 二叉树是一种树形数据结构,其中每个节点最多有两个子节点,通常称为“左子节点”和“右子节点”。 二叉树的根是唯一没有父节点的节点,而所有其他节点都有一个父节点和零个或两个子节点。 1.1 基础术语 节点(Node&…

ApiPost7使用介绍 | HTTP Websocket

一、基本介绍 创建项目(团队下面可以创建多个项目节点,每个项目可以创建多个接口): 参数描述库(填写参数时自动填充描述): 新建环境(前置URL、环境变量很有用)&#x…

【GitLab私有仓库】在Linux上用Gitlab搭建自己的私有库并配置cpolar内网穿透

文章目录 前言1. 下载Gitlab2. 安装Gitlab3. 启动Gitlab4. 安装cpolar5. 创建隧道配置访问地址6. 固定GitLab访问地址6.1 保留二级子域名6.2 配置二级子域名 7. 测试访问二级子域名 前言 GitLab 是一个用于仓库管理系统的开源项目,使用Git作为代码管理工具&#xf…

【搭建私人图床】使用LightPicture开源搭建图片管理系统并远程访问

文章目录 1.前言2. Lightpicture网站搭建2.1. Lightpicture下载和安装2.2. Lightpicture网页测试2.3.cpolar的安装和注册 3.本地网页发布3.1.Cpolar云端设置3.2.Cpolar本地设置 4.公网访问测试5.结语 1.前言 现在的手机越来越先进,功能也越来越多,而手机…

【STM32】学习笔记-SPI通信

SPI通信 SPI通信(Serial Peripheral Interface)是一种同步的串行通信协议,用于在微控制器、传感器、存储器、数字信号处理器等之间进行通信。SPI通信协议需要使用4个线路进行通信:时钟线(SCLK)、主输入/主输出线(MISO)、主输出/主…

算法leetcode|76. 最小覆盖子串(rust重拳出击)

文章目录 76. 最小覆盖子串:样例 1:样例 2:样例 3:提示:进阶: 分析:在这里插入图片描述 题解:rust:go:c:python:java: 76.…