synchronized关键字的作用、使用场景及锁升级过程。ReentrantLock与synchronized的区别及适用场景。

news2024/10/1 5:40:40

synchronized关键字的作用、使用场景及锁升级过程。

synchronized关键字的作用

synchronized是Java中的一个关键字,主要用于实现线程之间的同步。它的主要作用包括:

  1. 确保线程互斥地访问同步代码:当一个线程进入synchronized代码块或方法时,它将锁定该对象,其他线程需要等待锁释放后才能进入。这样可以确保在同一时间只有一个线程执行synchronized代码块或方法,从而避免多个线程同时修改共享资源导致的数据不一致或冲突的问题。

  2. 保证共享变量的可见性:synchronized除了实现互斥访问外,还可以保证共享变量的可见性。当一个线程释放锁时,会将对共享变量的更新刷新到主内存中,而当另一个线程获取锁时,会从主内存中重新读取最新的值,保证了线程间的数据可见性。

  3. 保证有序性:synchronized还可以确保代码的执行顺序。一个线程在执行完synchronized代码块或方法后,会释放锁并将对共享变量的修改刷新到主内存,而其他线程获取锁后会从主内存中重新读取最新的值。这样可以保证代码在不同线程间的执行顺序是按照预期的。

使用场景

synchronized常用于以下几种场景:

  1. 多线程需要访问同一资源:如文件、数据库连接或共享数据时,使用synchronized可以防止数据不一致或竞态条件的发生。

  2. 实现生产者-消费者问题、读写操作和初始化需求:在这些场景中,多个线程可能需要按照特定的顺序或规则来访问或修改数据,synchronized可以确保这些操作的正确执行。

  3. 需要对执行的操作进行排队,保证它们按顺序(串行)执行:在某些情况下,为了保证操作的顺序性,需要使用synchronized来同步线程的执行。

锁升级过程

在Java中,synchronized关键字的锁升级是指锁的状态从无锁状态到偏向锁状态,再到轻量级锁状态,最后到重量级锁状态的过程。这个过程是为了提高程序的性能和并发能力:

  1. 无锁状态:当一个线程访问一个同步代码块时,如果没有竞争,那么该线程可以直接进入临界区执行,不需要进行任何锁的操作。

  2. 偏向锁状态:当一个线程访问一个同步代码块时,如果没有竞争,那么该线程会将对象头中的标记位设置为偏向锁,并将线程ID记录在对象头中。下次该线程再次访问同步代码块时,无需进行任何锁的操作,可以直接进入临界区执行。

  3. 轻量级锁状态:当多个线程竞争同一个锁时,偏向锁会升级为轻量级锁。此时,每个线程会在自己的栈帧中创建一个锁记录(Lock Record)来保存锁对象的Mark Word,并尝试使用CAS(Compare and Swap)操作来获取锁。如果CAS操作成功,线程可以进入临界区执行;如果CAS操作失败,表示有其他线程竞争锁,那么线程会膨胀为重量级锁状态。

  4. 重量级锁状态:当多个线程竞争同一个锁时,轻量级锁会升级为重量级锁。此时,竞争锁的线程会进入阻塞状态,操作系统会将其挂起,直到锁被释放。其他线程再次竞争锁时,也会进入阻塞状态。

锁的升级过程是为了在无竞争的情况下尽量减少锁的操作和线程的切换,以提高程序的执行效率。只有在真正发生竞争时,才会升级为重量级锁,以保证线程的正确同步和互斥。

ReentrantLock与synchronized的区别及适用场景。

ReentrantLock与synchronized在Java并发编程中都是用于实现线程同步的重要机制,但它们之间存在一些关键的区别以及不同的适用场景。

一、区别

  1. 锁的获取与释放
    • synchronized:是Java的一个关键字,它隐式地获取和释放锁。当一个线程进入synchronized代码块或方法时,它会自动获取锁;当退出代码块或方法时,锁会自动释放。
    • ReentrantLock:是一个类,实现了Lock接口。它要求显式地调用lock()方法来获取锁,以及显式地调用unlock()方法来释放锁。
  2. 锁的公平性
    • synchronized:总是非公平锁,即无法保证等待时间最长的线程会首先获得锁。
    • ReentrantLock:可以设置为公平锁或非公平锁。在构造ReentrantLock时可以传入一个布尔值,true表示公平锁,false表示非公平锁(默认)。公平锁可以保证按照线程等待的先后顺序来获取锁。
  3. 响应中断
    • synchronized:不响应中断,即一个线程在等待锁的过程中,不能被中断。
    • ReentrantLock:提供了能够响应中断的锁获取操作,如lockInterruptibly()方法,允许在等待锁的过程中响应中断。
  4. 尝试非阻塞地获取锁
    • synchronized:没有提供尝试非阻塞地获取锁的机制。
    • ReentrantLock:提供了tryLock()方法,该方法尝试获取锁,如果获取成功立即返回true,否则返回false,不会使线程阻塞。
  5. 锁绑定多个条件
    • synchronized:与Object类中的wait()、notify()和notifyAll()方法结合,可以实现等待/通知机制,但这种方式较为原始且不够灵活。
    • ReentrantLock:提供了更加丰富的Condition API,每个ReentrantLock对象可以与一个或多个Condition对象(条件变量)关联,这为线程间的协调提供了更为灵活的控制。
  6. 性能
    • 在JDK 6及以后的版本中,synchronized的性能得到了显著提升,引入了偏向锁和轻量级锁等优化技术,使得synchronized在大多数场景下的性能与ReentrantLock相当甚至更优。
    • ReentrantLock在高度竞争的环境下,由于其提供了更灵活的尝试锁定和定时锁定等功能,可能会表现出更好的性能。

二、适用场景

  1. synchronized
    • 适用于简单的同步需求,如只需要基本的互斥访问控制。
    • 对性能要求较高,且不需要复杂同步特性的场景。
    • 开发者希望代码更加简洁,不需要手动管理锁的获取和释放。
  2. ReentrantLock
    • 适用于需要更复杂同步特性的场景,如需要公平锁、可中断锁、尝试非阻塞地获取锁等。
    • 在高度竞争和线程竞争激烈的场景下,ReentrantLock的性能可能优于synchronized。
    • 需要更灵活地控制线程等待和唤醒的场景,如使用多个Condition条件变量进行分组唤醒。

结论

ReentrantLock与synchronized各有优劣,选择哪种同步机制取决于具体的应用场景和需求。在简单的同步需求中,synchronized以其简洁性和良好的性能表现通常是首选;而在需要更复杂同步特性的场景中,ReentrantLock则提供了更灵活和强大的功能。

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

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

相关文章

Vue diff 算法介绍

首先我们来了解一下:diff 是什么? 通俗的讲,diff 就是比较两棵树,render 会生成两颗树,一棵新树 newVnode,一棵旧树 oldVnode,然后两棵树进行对比更新找差异就是 diff,全称 differe…

【cpp/c++ summary 工具】 Hunter 包管理器

Hunter 是一个跨平台cpp包管理器,点击查看支持的所有包的列表。 查看cmake是否满足 查看cmake是否满足Hunter版本要求: ubuntuDESKTOP-D7DRBER:~/CODE/mycpp/hunter-simple-master$ cmake --version cmake version 3.16.3CMake suite maintained and supported b…

88E1111使用技巧

一、88E1111简介 88E1111这款芯片是Marvel公司的产品,算是早期产品,但是市面上通用量较高,目前仍在大量使用,当然该公司也推出新产品,如88E1512,后续会有续篇,本篇文章重点讲述88E1111。 88E1…

66 使用注意力机制的seq2seq_by《李沐:动手学深度学习v2》pytorch版

系列文章目录 文章目录 系列文章目录动机加入注意力总结代码定义注意力解码器训练小结练习 我们来真的看一下实际应用中,key,value,query是什么东西,但是取决于应用场景不同,这三个东西会产生变化。先将放在seq2seq这个…

使用 SSH 连接 Docker 服务器:IntelliJ IDEA 高效配置与操作指南

使用 SSH 连接 Docker 服务器:IntelliJ IDEA 高效配置与操作指南 本文详细介绍了如何在 2375 端口未开放的情况下,通过 SSH 连接 Docker 服务器并在 Idea 中进行开发。通过修改用户权限、生成密钥对以及配置 SSH 访问,用户可以安全地远程操作…

Ubuntu 系统崩了,如何把数据拷下来

问题描述: Linux系统中安装输入法后,重启后,导致系统无法进入,进入 recovery mode下的resume 也启动不了,所以决定将需要的东西复制到U盘 解决方案: 1.重启ubuntu,随即点按Esc进入grub菜单&am…

Linux shell脚本set -e的作用详解

文章目录 功能详细解释示例不使用 set -e 的情况总结 set -e 是一个用于控制脚本行为的命令,它的作用是: 功能 当脚本运行时,set -e 会确保一旦某个命令返回非零的退出状态(即执行失败),整个脚本会立即停止…

Docker面试-24年

1、Docker 是什么? Docker一个开源的应用容器引擎,是实现容器技术的一种工具,让开发者可以打包他们的应用以及环境到一个镜像中,可以快速的发布到任何流行的操作系统上。 2、Docker的三大核心是什么? 镜像:Docker的…

在 Kali Linux 中安装 Impacket

步骤 1:更新系统 打开终端并确保你的系统是最新的: sudo apt update && sudo apt upgrade -y 步骤 2:安装依赖 在安装 Impacket 之前,你需要确保安装了 Python 和一些必要的依赖。通常,Kali 已经预装了 Pytho…

工作日志:el-table在无数据情况下,出现横向滚动条。

1、遇到一个警告。 原因:中的组件不能呈现动画的非元素根节点。 也就是说,Transition包裹的必须是一个单根的组件。 2、el-table在无数据情况下,出现横向滚动条,大概跟边框的设置有关系。 开始排查。 给.el-scrollbar加了一个…

Linux 线程同步

前言 上一期我们介绍了线程互斥,并通过加锁解决了多线程并发访问下的数据不一致问题!本期我们来介绍一下同步问题! 目录 前言 一、线程同步 • 线程同步的引入 • 同步的概念 理解同步和饥饿问题 • 条件变量 理解条件变量 • 同步…

TypeScript 算法手册 【数组基础知识】

文章目录 1. 数组简介1.1 数组定义1.2 数组特点 2. 数组的基本操作2.1 访问元素2.2 添加元素2.3 删除元素2.4 修改元素2.5 查找元素 3. 数组的常见方法3.1 数组的创建3.2 数组的遍历3.3 数组的映射3.4 数组的过滤3.5 数组的归约3.6 数组的查找3.7 数组的排序3.8 数组的反转3.9 …

AI写作赋能数据采集,开启无限可能性

由人工智能 AI 掀起的新一轮科技革命浪潮,正在不断推动社会进步、各行各业升级发展,深刻影响人们的生活方式,引领我们进入一个充满无限可能的新时代。 那么在数据采集方面,人工智能 AI 可以做什么呢? 下面是搜集网络…

开源在线表结构设计工具

Free, simple, and intuitive database design tool and SQL generator. drawDB在线体验 Discord X drawDB DrawDB is a robust and user-friendly database entity relationship (DBER) editor right in your browser. Build diagrams with a few clicks, export sql scri…

若依--文件上传前端

前端 ry的前端文件上传单独写了一个FileUpload.Vue文件。在main.js中进行了全局的注册,可以在页面中直接使用文件上传的组件。全局导入 在main.js中 import 组件名称 from /components/FileUpLoadapp.compoent(组件名称) //全局挂载组件在项目中使用 组件命令 中…

定时器定时中断定时器外部中断

TIM的函数 // 恢复缺省设置 void TIM_DeInit(TIM_TypeDef* TIMx); // 时基单元初始化,第一个参数TIMx选择某个定时器,第二个参数是结构体,包含了配置时基单元的一些参数。 void TIM_TimeBaseInit(TIM_TypeDef* TIMx, TIM_TimeBaseInitTypeDe…

28 Vue3之搭建公司级项目规范

可以看到保存的时候ref这行被提到了最前面的一行 要求内置库放在组件的前面称为auto fix,数组new arry改成了字面量,这就是我们配置的规范 js规范使用的是airbnb规范模块使用的是antfu 组合prettier&eslint airbnb规范: https://github…

《More Effective C++》的学习

引用与指针 没有所谓的null reference reference一定需要代表某个对象,所以C要求reference必须有初值。 QString &s; 使用reference可能比使用pointer更高效。 因为reference一定是有效的,而指针可能为空(需要多加一个判断&#xff0…

Springboot3 + MyBatis-Plus + MySql + Vue + ProTable + TS 实现后台管理商品分类(最新教程附源码)

Springboot3 MyBatis-Plus MySql Uniapp 商品加入购物车功能实现(针对上一篇sku) 1、效果展示2、数据库设计3、后端源码3.1 application.yml 方便 AliOssUtil.java 读取3.2 model 层3.2.1 BaseEntity3.2.1 GoodsType3.2.3 GoodsTypeSonVo3.3 Controll…

论文翻译 | LLaMA-Adapter :具有零初始化注意的语言模型的有效微调

摘要 我们提出了一种轻量级的自适应方法,可以有效地将LLaMA微调为指令遵循模型。lama - adapter采用52K自指导演示,在冻结的LLaMA 7B模型上只引入1.2M可学习参数,在8个A100 gpu上进行微调花费不到一个小时。具体来说,我们采用了一…