锁( ReentrantLock,Synchronized)

news2024/12/26 16:33:21

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.coloradmin.cn/o/964159.html

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

相关文章

idea中设置指定图片为项目站标

前提是准备好一张图片 在idea中创建imgs文件夹&#xff0c;放入图片 创建一个HTML文件 建立链接link标签&#xff0c;链接照片即可 <link href"../02css/imgs/2.jpg" rel"shortcut icon" type"image/x-icon"> 执行效果如下图所示&…

音频——I2S 左对齐模式(三)

I2S 基本概念飞利浦(I2S)标准模式左(MSB)对齐标准模式右(LSB)对齐标准模式DSP 模式TDM 模式 文章目录 I2S left波形图逻辑分析仪抓包 I2S left I2S 左对齐标准 标准左对齐格式的数据的 MSB 没有相对于 BCLK 延迟一个时钟。左对齐格式的左右声道数据的 MSB 在 LRCLK 边沿变化后…

斐波那契数【动态规划】

斐波那契数 斐波那契数 &#xff08;通常用 F(n) 表示&#xff09;形成的序列称为 斐波那契数列 。该数列由 0 和 1 开始&#xff0c;后面的每一项数字都是前面两项数字的和。也就是&#xff1a; F(0) 0&#xff0c;F(1) 1 F(n) F(n - 1) F(n - 2)&#xff0c;其中 n >…

Golang:微服务常用代码分层结构

1.代码结构 代码分层结构是一个老生常谈的话题&#xff0c;好的代码结构能够使得系统易于理解、开发及维护&#xff0c;如果代码结构很混乱就会使得不同层级的代码块耦合&#xff0c;导致难以维护和拓展。 比较经典的代码结构&#xff08;宏观&#xff09;有Web的MVC模式分层结…

SpringBoot整合websockt实现消息对话

文章目录 前言websockt什么是websockt&#xff1f;websockt和Socket区别代码部分实战应用 前言 websockt 什么是websockt&#xff1f; WebSocket是一种在Web应用程序中实现实时双向通信的技术。Web应用程序通常是基于HTTP协议的&#xff0c;HTTP是一种请求/响应式的协议&…

【服务器使用基础】---华为云云耀云服务器实例使用实践

&#x1f996;我是Sam9029&#xff0c;一个前端 Sam9029的CSDN博客主页:Sam9029的博客_CSDN博客-JS学习,CSS学习,Vue-2领域博主 **&#x1f431;‍&#x1f409;&#x1f431;‍&#x1f409;恭喜你&#xff0c;若此文你认为写的不错&#xff0c;不要吝啬你的赞扬&#xff0c;求…

肖sir__linux详解__003(vim命令)

linux 文本编辑命令 作用&#xff1a;用于编辑一个文件 用法&#xff1a;vim 文件名称 或者vi &#xff08;1&#xff09;编辑一个存在的文档 例子&#xff1a;编辑一个file1文件 vim aa &#xff08;2&#xff09;编辑一个文件不存在&#xff0c;会先创建文件&#xff0c;再…

Python-图像拼接神器-stitching

多幅图像的拼接 采用这个包&#xff0c;图像拼接结果很好~ 代码只需要三四行 import stitching import cv2imgs ["data/test02/1Hill.jpg","data/test02/2Hill.jpg","data/test02/3Hill.jpg",] stitcher stitching.Stitcher() panorma stit…

postgresql-多表连接

postgresql-多表连接 内连接查询左外连接查询右外连接查询全外连接查询交叉连接查询简写 总结 内连接查询 内连接用于返回两个表中匹配的数据行&#xff0c;使用关键字INNER JOIN表示&#xff0c;也可以简写成JOIN&#xff1b; selecte.first_name ,d.department_id fromcps…

无涯教程-JavaScript - POISSON函数

POISSON函数取代了Excel 2010中的POISSON.DIST函数。 描述 该函数返回泊松分布。泊松分布的常见应用是预测特定时间的事件数。 语法 POISSON(x,mean,cumulative)争论 Argument描述Required/OptionalXThe number of events.RequiredMeanThe expected numeric value.Require…

leecode学习(1)

一、题目 给定一个数组nums和一个目标值target,请你再该数组中找出和为目标值的那两个数&#xff0c;并返回数组的下标&#xff0c;你可以假设输入只会对应一个答案&#xff0c;但是数组的同一个元素不能使用两次。 二、解题思路 目的就是要求出两数之和等于目标值嘛。 就是…

探索树堆Treap和红黑树的优势和劣势

探索树堆Treap和红黑树的优势和劣势 一、背景知识二、树堆&#xff08;Treap&#xff09;的介绍三、红黑树&#xff08;RB-Tree&#xff09;的介绍四、树堆&#xff08;Treap&#xff09;与红黑树&#xff08;RB-Tree&#xff09;的比较总结 博主简介 &#x1f4a1;一个热爱分享…

王道考研数据结构

文章目录 C 环境准备官方文档环境准备在线运行VSCode 环境报错解决 绪论线性表顺序表链表错题 栈、队列和数组栈队列栈的应用之中缀转后缀特殊矩阵用数组压缩存储错题 串模式匹配之暴力和KMP 树与二叉树二叉树树和森林哈夫曼树和哈夫曼编码并查集错题 图图的基本概念图的存储及…

LeetCode494. 目标和

494. 目标和 文章目录 [494. 目标和](https://leetcode.cn/problems/target-sum/)一、题目二、题解方法一&#xff1a;目标和路径计数算法方法二&#xff1a;01背包方法三&#xff1a;01背包一维数组 一、题目 给你一个非负整数数组 nums 和一个整数 target 。 向数组中的每个…

IPC进程间通信及示例代码

一. 什么是进程通信 进程通信&#xff08; InterProcess Communication&#xff0c;IPC&#xff09;就是指进程之间的信息交换。实际上&#xff0c;进程的同步与互斥本质上也是一种进程通信&#xff08;这也就是待会我们会在进程通信机制中看见信号量和 PV 操作的原因了&#x…

Ubuntu18.04使用Systemback制作系统镜像并还原

系列文章目录 文章目录 系列文章目录前言一、下载Systemback工具二、制作系统镜像到U盘三、安装制作系统 前言 在Ubuntu系统中开发项目时&#xff0c;有时会希望将项目移植到另外一台计算机&#xff08;如工控机等&#xff09;上进行部署&#xff0c;通常会在新计算机中安装Ub…

Qt +VTK+Cmake 编译和环境配置(第二篇,中级篇, 重新编译)

1.下载VTK和Cmake 这里不介绍了。我的VTK 8.2.0 cmake 3.27.4 就是不服这编译器了。重新来一次 打开Cmake&#xff0c;把VTK源文件路径和目标路径设置一下&#xff08;目标路径自己设置&#xff0c;随意&#xff09; 点击Configure&#xff1a;。 点击下一步 选择好 Qt的gcc…

国际版阿里云/腾讯云:弹性高性能计算E-HPC入门概述

入门概述 本文介绍E-HPC的运用流程&#xff0c;帮助您快速上手运用弹性高性能核算。 下文以创立集群&#xff0c;在集群中安装GROMACS软件并运转水分子算例进行高性能核算为例&#xff0c;介绍弹性高性能核算的运用流程&#xff0c;帮助您快速上手运用弹性高性能核算。运用流程…

selenium 自动化测试——环境搭建

安装python&#xff0c;并且使用pip命令安装 selenium pip3 install selenium 然后尝试第一次使用selenium 完成一个简单的测试自动化脚本 from selenium import webdriver from selenium.webdriver.common.by import By import timedriver webdriver.Chrome() driver.get(…

A 股个股资金流排行 API 数据接口

A 股个股资金流排行 API 数据接口 全量股票资金流排名&#xff0c;多时间区间&#xff0c;全量A股数据。 1. 产品功能 支持所有A股资金流数据查询&#xff1b;每日定时更新数据&#xff1b;支持多时间段查询&#xff1b;超高的查询效率&#xff0c;数据秒级返回&#xff1b;数…