Java基础--->并发部分(2)【Java中的锁】

news2024/11/25 0:36:53

文章目录

  • synchronized和ReentrantLock的区别
  • Java中锁的名词
  • synchronized锁
  • ReentrantLock锁

synchronized和ReentrantLock的区别

synchronizedReentrantLock 都可以用来实现 Java 中的线程同步。它们的作用类似,但是在用法和特性上还是有一些区别的。

  1. synchronized 是 Java 内置的关键字,可以修饰代码块和方法,自动获取锁、释放锁,可以避免因为锁的释放问题导致的死锁;而 ReentrantLock 是Java类,只能对某段代码进行修饰,需要手动进行锁的获取和释放。
  2. ReentrantLock 的灵活性更高,比如支持可重入锁、支持公平锁和非公平锁、支持多个条件变量等,而 synchronized 则相对简化,更加方便快捷。
  3. 多个线程争抢 synchronized 的锁时,其中一个线程拿到锁后,其他线程进入锁池等待,直到持有锁的线程释放锁,其他等待线程才能继续竞争锁。而 ReentrantLock 可以灵活地控制锁的公平性和非公平性,以及等待的顺序。
  4. synchronized 在底层是依赖于 JVM 实现的,而 ReentrantLock 是使用 java.util.concurrent 包提供的一种基于接口的可重入锁,这种可重入锁的性能比较优秀,适用于高并发场景。

综上所述,ReentrantLock 更加灵活,支持更多的特性和操作,适用于复杂的场景;而 synchronized 更加简化,使用方便,适用于一些简单的场景。

Java中锁的名词

​ 每个名字并不都代表一个锁,有些锁的名字指的是锁的特性,锁的设计,锁的状态

乐观锁(不加锁):认为并发的操作,不加锁的方式实现是没有问题的,每次操作前判断(CAS,自旋)是否成立,不加锁实现。

悲观锁:认为对于同一个数据的并发操作,一定是会发生修改的,即使没有修改,也会认为修改。认为并发操作肯定会有问题,必须加锁,对于同一个数据的并发操作,悲观锁采用加锁的形式

总结:悲观锁适合写操作非常多的场景,乐观锁适合读操作非常多的场景,不加锁会带来大量的性能提升。

悲观锁在Java中使用的话就是利用各种的锁

乐观锁在Java中使用的话是无锁编程,常常采用的是CAS算法,典型的例子就是原子类,通过CAS自旋实现原子操作的更新

可重入锁:当一个线程获取到外层方法的同步锁对象后,可以获取到内部其他方法的同步锁,如果不使用,就容易出现死锁

在这里插入图片描述

读写锁(ReentrantReadWriteLock):支持读,写加锁,总的来说就是如果是读操作,就不加锁,如果一旦有写操作,那么读写互斥

特点:读读不互斥,读写互斥,写写互斥
加读锁是防止在另外的线程在此时写入数据,防止读取脏数据

一个读写锁同时只能有一个写者或多个读者(与CPU数相关),不能同时有读者和写者

​ 在读写锁保持期间也是抢占失效的

​ 如果读写锁当前没有读者,也没有写者,那么写者可以立刻获得读写锁,否者它必须自旋在那,直到没有读者或者写者。如果读写锁没有写者,那么读者可以立即获得该读写锁,否则读者必须自旋在那里,直到写者释放该读写锁。

分段锁(不是锁):是一种思想,将数据分段,并在每个分段上单独加锁,以此来将锁的粒度拆分,提高效率

自旋锁(不是锁):是一种自旋思想,是以自旋的方式重试获取,当线程抢锁失败后,重试几次,要是抢到锁了就继续,抢不到就阻塞线程,目的就是还是为了尽量不要阻塞线程。

​ 由此可见,自旋锁是比较消耗CPU的,因为要不断的循环重试,不会释放CPU资源。加锁时间普遍较短的场景非常适合自旋锁,可以极大提高锁的效率

共享锁/独占锁
​ 共享锁:读写锁中的读锁,该锁可被多个线程持有,并发访问共享资源
​ 独占锁:互斥锁,synchronized ReentrantLock都属于独占锁,一次之能被一个线程持有

公平锁/非公平锁
​ 公平锁:根据线程先来后到公平的获取锁,例ReentrantLock就可以实现公平锁,按照锁请求的顺序分配,拥有稳定获得锁的机会
​ 非公平锁:不按照锁请求顺序分配,没有先来后到,谁抢到谁获得执行权,synchronized 是非公平锁

​ ReentrantLock默认是非公平锁,但是底层可以通过AQS来实现线程调度,所以可以使其变成公平锁

synchronized锁

对象结构

​ 在Hotspot虚拟机中,对象在内存中的布局分为三块区域:对象头、实例数据和对齐填充;

​ 对象头中有一块区域称为 Mark Word,用于存储对象自身的运行时数据,如哈 希码(HashCode)、GC 分代年龄、锁状态标志、线程持有的锁、偏向线程 ID 等等。

在synchronized锁的底层实现中,提供锁的状态,又来区别对待
这个锁的状态在同步锁的对象头中,有一个区域叫Mark Word中存储

偏向锁/轻量级锁/重量级锁(都是锁的状态):这四种状态都不是Java语言中的锁,而是JVM为了提高锁(synchronized)的获取与释放效率而做的优化

​ 无锁
偏向锁
​ 一直是一个线程访问,线程ID被记录,快速获取锁
轻量级锁
​ 当锁状态为偏向锁时,又继续有其他线程访问,此时升级为轻量锁,没有获取到锁的线程,不会阻塞,继续不断尝试获取锁
重量级锁
​ 当锁的状态为轻量级锁时,线程自旋达到一定的次数,进入达到阻塞状态,锁状态升级为重量级锁,等待操作系统调度

synchronized锁的实现

​ synchronized锁是依赖底层编译后的指令来控制的,需要我们提供一个同步对象,来记录锁状态

​ 线程在进入synchronized代码块时候会自动获取内部锁,这个时候其他线程访问时会被阻塞,直到执行完或抛出异常或者调用了wait方法,都会释放锁资源,主内存把变量读取到自己工作内存,在退出时会把工作内存的值写入到主内存,保证原子性
​ synchronized基于进入和退出监视器对象来实现方法同步和代码块同步
​ 设置ACC_SYNCHRONIZED标记是否为同步方法,调用指令先检查是否设置,如果设置了,需要monitorenter表明线程进入该方法,使用monitorexit退出该方法
​ 在虚拟机执行monitorenter指令时,首先要尝试获取对象的锁,如果当前线程拥有了这个对象的锁,把锁的计数器+1,当执行monitorexit指令时将所得计数器-1,当计数器为0时,锁就被释放了
​ Java中synchronized通过在对象头设置标记,达到了获取锁和释放锁的目的

ReentrantLock锁

​ ReentrantLock 是 java.util.concurrent.locks 包 下 的 类,ReentrantLock 基于 AQS,在并发编程中它可以实现公平锁和非公平锁来

​ ReentrantLock 类内部总共存在 Sync、NonfairSync、FairSync 三个类,

​ NonfairSync 与 FairSync 类 继 承 自 Sync 类 , Sync 类 继 承 自 AbstractQueuedSynchronizer 抽象类。对共享资源进行同步,同时和 synchronized 一样,

​ ReentrantLock 支持可重入,

除此之外,ReentrantLock 在调度上更灵活,支持更多丰富的功能。

​ NonfairSync 类继承了 Sync 类,表示采用非公平策略获取锁,其实现 了 Sync 类中抽象的 lock 方法.

  • 非公平
NonfairSync
final void lock() {
         if (compareAndSetState(0, 1))//线程来到后,直接尝试获取锁,是非公平
             setExclusiveOwnerThread(Thread.currentThread());
         else//获取不到
             acquire(1);
}

FairSync 类也继承了 Sync 类,表示采用公平策略获取锁,其实现了 Sync 类中 的抽象 lock 方法.
  • 公平实现
FairSync
final void lock() {
            acquire(1);
            }
            ```

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

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

相关文章

【2023/05/20】Visual Basic

Hello!大家好,我是霜淮子,2023倒计时第15天。 Visual Basic是一种广泛应用于Windows操作系统的编程语言,它是Microsoft公司开发的一种面向对象的编程语言,以其简单、易学、易用的特点受到广泛欢迎。本文旨在介绍Visual…

2023年申请美国大学,需要SAT/ACT成绩吗?

受疫情影响,2021 和 2022 年申请美国大学时,许多大学都放宽了SAT/ACT门槛,不强行要求学生提交标化成绩。今年3月,理工大牛院校 MIT 率先打破了这个局面,宣布恢复 SAT/ACT 标化成绩要求,随后几个大学也陆续宣…

Java --- 云尚办公用户管理模块实现

目录 一、用户管理 1.1、数据库表 1.2、使用代码生成器生成相关代码 1.3、后端代码 1.4、前端代码 二、用户与角色功能实现 一、用户管理 1.1、数据库表 CREATE TABLE sys_user (id BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT 会员id,username VARCHAR(20) NOT NU…

Java面试知识点(全)-spring面试知识点一

Java面试知识点(全) 导航: https://nanxiang.blog.csdn.net/article/details/130640392 注:随时更新 Spring原理 Spring ioc概念:控制权由对象本身转向容器;由容器根据配置文件去创建实例并创建各个实例之间的依赖关系。核心&am…

学术会议参会经验分享一(参会前的准备工作)

前前后后参加了两次学术会议,一次是今年三月份在深圳,另一次是在五月份在南宁,并且两次都进行了主题演讲。总的来说,我感觉参加学术会议重要的是自身能力的提升,比如说演讲、PPT制作等更方面的能力。下面我来分享一些我…

USRP概念基础

GBIC Gigabit Interface Converter的缩写,是将千兆位电信号转换为光信号的接口器件。GBIC设计上可以为热插拔使用。 SFP SFP (Small Form Pluggable)可以简单理解为GBIC(Gigabit Interface Converter的缩写)升级版本,是将千兆位电信号转换为光信号的接口器件,可以热插…

python字符串拼接

首先 什么是字符串拼接 我们来看一个段代码 print("你好""小猫猫")运行结果如下 这是一个最简单的演示 字符串 与 字符串的拼接 两个字符串字面量可以直接用加号 合并成一个字符串 当然 直接这里 字面量字面量 直接写上去看着会非常傻 所以 一般都是 变…

( 动态规划) 516. 最长回文子序列 ——【Leetcode每日一题】

❓516. 最长回文子序列 难度:中等 给你一个字符串 s ,找出其中最长的回文子序列,并返回该序列的长度。 子序列定义为:不改变剩余字符顺序的情况下,删除某些字符或者不删除任何字符形成的一个序列。 示例 1&#xf…

MarkDown语法2

MarkDown语法2 一、基本语法 1. 标题 一级标题:# 一级标题二级标题:## 二级标题 2. 字体 斜体:*斜体*,_斜体_粗体:**粗体**,__粗体__粗斜体:***粗斜体***, ___粗斜体___ 3. 线 分割线:&a…

java常用工具之Objects类

目录 简介一、对象判空二、 对象为空时抛异常三、 判断两个对象是否相等四、 获取对象的hashcode五、 比较两个对象六、比较两个数组七、 小结 简介 Java 的 Objects 类是一个实用工具类,包含了一系列静态方法,用于处理对象。它位于 java.util 包中&…

七、Spring Cloud Alibaba-Sentinel

一、引言 1、了解服务可用性问题,服务挂掉原因 缓存击穿、单点故障、流量激增、线程池爆满、CPU飙升、DB超时、缺乏容错机制或保护机制、负载不均、服务雪崩、异常没处理等。 服务雪崩效应:因服务提供者的不可用导致服务调用者的不可用,并将…

Doxygen源码分析: QCString类依赖的qstr系列C函数浅析

2023-05-20 17:02:21 ChrisZZ imzhuofoxmailcom Hompage https://github.com/zchrissirhcz 文章目录 1. doxygen 版本2. QCString 类简介3. qstr 系列函数浅析qmemmove()qsnprintfqstrdup()qstrfree()qstrlen()qstrcpy()qstrncpy()qisempty()qstrcmp()qstrncmp()qisspace()qstr…

C++ VTK网格模型补洞填孔

程序示例精选 C VTK网格模型补洞填孔 如需安装运行环境或远程调试&#xff0c;见文章底部个人QQ名片&#xff0c;由专业技术人员远程协助&#xff01; 前言 这篇博客针对<<C VTK网格模型补洞填孔>>编写代码&#xff0c;代码整洁&#xff0c;规则&#xff0c;易读。…

如何将Windows图片查看器的背景颜色改成浅色?

现在大家基本都在使用Win10系统&#xff0c;我们在双击查看图片时&#xff0c;系统默认使用系统自带的图片&#xff08;照片&#xff09;查看器去打开图片。图片查看器的背景色默认是黑色的&#xff0c;如下所示&#xff1a;&#xff08;因为大家可能会遇到同样的问题&#xff…

飞浆AI studio人工智能课程学习(3)-在具体场景下优化Prompt

文章目录 在具体场景下优化Prompt营销场景办公效率场景日常生活场景海报背景图生成办公效率场景预设Prompt 生活场景中日常学习Prompt: 给写完的代码做文档 将优质Prompt模板化Prompt 1:Prompt 1:Prompt 2步骤文本过长而导致遗失信息的示例修改后 特殊示例 如何提升安全性主要目…

最近最少使用(LRU, Least recently used)缓存算法_华为2023

思路 性能限制很高、数据量很大时&#xff0c;cin、cout肯定是不够快的。 &#xff08;1&#xff09;可以利用getchar()速度快的特性设计快读函数读取整数&#xff0c;可以做到用scanf()函数5倍的速度读入任意整数&#xff1a; #include<cstdio> // 仅正整数可用 #defi…

u盘恢复数据方法有哪些(u盘恢复数据方法)

嘿小伙伴们&#xff0c;今天咱们来聊聊一个小问题&#xff0c;就是当我们的U盘不小心丢失了重要数据&#xff0c;怎么办呢&#xff1f;没关系&#xff0c;这里我就为大家介绍几种U盘恢复数据的方法。 u盘恢复数据方法有哪些 1,首先&#xff0c;最简单粗暴的方法就是使用Windo…

Redis分片集群

目录 搭建分片集群 散列插槽 集群伸缩 故障转移 数据迁移 RedisTemplate访问分片集群 搭建分片集群 主从&#xff08;一个主节点、多个子节点&#xff0c;读写分离&#xff09;和哨兵&#xff08;解决主节点宕机问题&#xff09;可以解决高可用、高并发读的问题。但是依然…

如何更改pdf文件的默认打开程序?

在Windows系统中&#xff0c;有时安装一些软件或执行一些操作&#xff0c;会自动将打开某种类型文件的默认程序给修改掉&#xff0c;这样后续打开文件时可能会很别扭&#xff0c;于是我们想把打开文件的默认工具设置指定的软件。 以打开pdf文件为例&#xff0c;某天打开pdf文件…

基于Zynq的雷达10Gbps高速PCIE数据采集卡方案(三)软件设计

4.1 引言 本章基于第二章的分析结论&#xff0c;进行系统软件设计。软件设计包括逻辑设计、嵌入 式软件设计和上位机软件设计。在逻辑设计中&#xff0c;对 ADC 模块、 Aurora 模块、 DDR3 SDRAM 模块和 PCIE 模块进行分析和设计&#xff0c;在 Vivado 软件提供的 …