一文弄懂synchronized

简述

synchronized是什么?

synchronized 关键字是一种同步锁,它可以保证在一个时刻只有一个线程可以执行某段代码。synchronized 关键字可以用在方法、代码块、静态方法和静态代码块上。

synchronized怎么用?

synchronized是Java中用于实现线程同步的关键字,它可以修饰方法或代码块。

  1. 修饰方法:当一个方法被synchronized修饰时,表示该方法是一个同步方法。同一时间只能有一个线程执行该方法,其他线程需要等待。
public synchronized void method() {
  // 这里是同步代码块
}
  1. 修饰代码块:当一个代码块被synchronized修饰时,表示该代码块是一个同步代码块。同一时间只能有一个线程进入该代码块,其他线程需要等待。
public class Example {

    public static void main(String[] args) {
        final int[] number = {1, 2, 3, 4, 5};

        for (int i = 0; i < 5; i++) {
            new Thread(() -> {
                synchronized (number) {
                    // 这里是同步代码块
                    System.out.println(number[i]);
                }
            }).start();
        }
    }
}

锁的是什么

普通同步方法>锁的是当前实力对象。
静态同步方法>锁的是当前类的Class对象。
同步方法快>锁的是synchonized括号里配置的对象。

注意事项

当使用synchronized修饰代码块时,应该尽量控制同步代码块的范围,避免锁的竞争过于频繁,以提高程序的性能。同时,锁对象的选择也很重要,应该选择合适的锁对象以避免不必要的线程等待和资源竞争。

原理

synchronized修饰代码块和方法的底层原理类似,都是通过对象头中的锁标记位来实现的。

修饰方法

进入方法:当线程调用一个被synchronized修饰的方法时,会尝试获取该方法所属对象的锁。
获取锁:如果对象的锁标记位为"unlocked"状态,则当前线程可以获取到锁,并将锁标记位设置为"locked"状态,表示该对象被当前线程锁定。
执行方法体:线程获取到锁后,会执行synchronized修饰的方法体中的代码。
释放锁:当方法执行完毕或抛出异常时,会自动释放对象的锁,将锁标记位重新设置为"unlocked"状态。

注意点

需要注意的是,synchronized修饰方法时,默认锁定的是当前对象实例(this),即当前方法所属的对象。如果是静态方法,锁定的是当前类的Class对象。

//1.静态方法 
public static synchronized void method() {
    // 该方法被当前类的Class对象锁定
    // ...
}
//2.普通方法
public synchronized void method() {
    // 该方法被当前实例对象锁定
    // ...
}

修饰代码块

进入代码块:当线程进入一个被synchronized修饰的代码块时,会尝试获取对象的锁。
获取锁:如果对象的锁标记位为"unlocked"状态,则当前线程可以获取到锁,并将锁标记位设置为"locked"状态,表示该对象被当前线程锁定。
阻塞或执行:如果对象的锁标记位为"locked"状态,表示该对象已被其他线程锁定。当前线程会被阻塞,直到锁标记位变为"unlocked"状态时才能继续执行。
释放锁:当线程执行完synchronized代码块后,会释放对象的锁,将锁标记位重新设置为"unlocked"状态,使其他线程能够获取到锁并执行。

public void method() {
    synchronized (lock) {
        // 该代码块被lock对象锁定
        // ...
    }
}

锁的高级特征

JVM在实现锁的过程中采用了多种锁的机制,包括偏向锁、轻量级锁和重量级锁,并且会根据锁竞争的情况自动进行锁升级和降级。下面是对这些锁的机制和锁升级的简要说明:

偏向锁(Bias Locking):

简介

偏向锁是一种乐观锁策略,适用于大部分情况下只有一个线程对锁进行竞争的场景。
偏向锁的目标是减少无竞争的情况下对锁的开销,提高程序的性能。
当一个线程获取到偏向锁后,JVM会将线程的标识记录在对象头中,之后该线程再次获取锁时无需进行同步操作,从而提高了程序的执行效率。

实现原理

轻量级锁(Lightweight Locking):

简介

当多个线程对同一个锁进行竞争时,JVM会将锁升级为轻量级锁。
轻量级锁使用CAS(Compare and Swap)操作来实现对锁的获取和释放,避免了线程阻塞和唤醒的开销。
如果竞争激烈,多个线程同时尝试获取锁,那么轻量级锁会膨胀为重量级锁。

实现原理

重量级锁(Heavyweight Locking):

简介

当轻量级锁膨胀失败或竞争过于激烈时,JVM会将锁升级为重量级锁。
重量级锁使用操作系统的互斥量来实现对锁的获取和释放,需要涉及线程的阻塞和唤醒。
线程在获取重量级锁时会进入阻塞状态,当锁被释放时,JVM会从阻塞的线程中选择一个进行唤醒。
锁的升级和降级是根据锁竞争的情况动态进行的,以提高程序的性能和吞吐量。当JVM检测到锁竞争较少时,会尝试将重量级锁降级为轻量级锁,以提高并发性能。反之,如果锁竞争激烈,JVM会将轻量级锁膨胀为重量级锁,以避免不必要的自旋和消耗。

实现原理

需要注意的是,锁的升级和降级过程对于开发者来说是透明的,无需手动干预。JVM会根据实际情况自动进行锁的升级和降级操作,以达到更好的性能和可伸缩性。

这些锁的机制和锁升级是JVM内部的实现细节,对于开发者来说,只需要了解它们的存在和基本原理,以正确地使用synchronized关键字来实现线程安全的同步。

优秀文章传送门:
https://zhuanlan.zhihu.com/p/571793506
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

婚庆策划小程序制作教程

本文将向你展示如何使用小程序制作平台&#xff0c;轻松制作婚庆策划小程序。只需按照以下步骤操作&#xff0c;你就能拥有自己的专业级婚庆策划小程序。 登录小程序制作平台 首先&#xff0c;你需要登录小程序制作平台。在浏览器搜索乔拓云&#xff0c;然后使用你的账号登录。…

Promise的并发控制 - 从普通并发池到动态并发池

一、场景 给你一个有200个URL的数组&#xff0c;通过这些URL来发送请求&#xff0c;要求并发请求数不能超过五个。 这是一道很常考的面试题&#xff0c;接下来让我们来学习一下Promise并发控制 二、普通并发池的实现 主要思路就是&#xff0c;判断当前队列是否满&#xff0c;…

【word技巧】ABCD选项如何对齐?

使用word文件制作试卷&#xff0c;如何将ABCD选项全部设置对齐&#xff1f;除了一直按空格或者Tab键以外&#xff0c;还有其他方法吗&#xff1f;今天分享如何将ABCD选项对齐。 首先&#xff0c;我们打开【替换和查找】&#xff0c;在查找内容输入空格&#xff0c;然后点击全部…

基于野狗算法的无人机航迹规划-附代码

基于野狗算法的无人机航迹规划 文章目录 基于野狗算法的无人机航迹规划1.野狗搜索算法2.无人机飞行环境建模3.无人机航迹规划建模4.实验结果4.1地图创建4.2 航迹规划 5.参考文献6.Matlab代码 摘要&#xff1a;本文主要介绍利用野狗算法来优化无人机航迹规划。 1.野狗搜索算法 …

微信小程序:实现多个按钮提交表单

效果 核心步骤 通过data-type给不同按钮进行设置&#xff0c;便于很好的区分不同按钮执行不同功能 data-type"" 完整代码 wxml <form action"" bindsubmit"formSubmit"><button style"margin-bottom:5%" data-type"pa…

​C++内存模型

c语言分区:栈、堆、全局/静态存储区、常量存储区、代码区(.text段)、自由存储区 1、栈区&#xff08;stack&#xff09;— 由编译器自动分配释放&#xff0c;存放函数的参数值&#xff0c;局部变量的值等。其操作方式类似于数据结构中的栈。向下生长 2、堆区&#xff08;heap&…

超声波俱乐部分享:百度世界大会点燃AI创业者新希望

10月22日&#xff0c;2023年第十三期超声波俱乐部内部分享会在北京望京举行。本期的主题是&#xff1a;百度世界大会点燃AI创业者新希望。 到场的嘉宾有&#xff1a;超声波创始人杨子超&#xff0c;超声波联合创始人、和牛商业创始人刘思雨&#xff0c;中国国际经济交流中心研…

MFC String类的初始化学习

之前写过CString的用法&#xff1b; VC CString 编程实例图解_bcbobo21cn, cstring-CSDN博客 下面单独看一下CString的各种初始化方式&#xff1b; void CTest2View::OnDraw(CDC* pDC) {CTest2Doc* pDoc GetDocument();ASSERT_VALID(pDoc);// TODO: add draw code for nati…

vscode1.83远程连接失败

&#xff08;报错信息忘记截图了 总之卡在vscode-server.tar.gz的下载那里&#xff0c;一直404&#xff0c;删了C:\Users\Administrator\.ssh\known_hosts也不管用 看了一下vscode1.83的commitID为a6606b6ca720bca780c2d3c9d4cc3966ff2eca12&#xff0c;网友说可以通过以下网…

C++笔记之动态数组的申请和手动实现一个简单的vector

C笔记之动态数组的申请和手动实现一个简单的vector code review! 文章目录 C笔记之动态数组的申请和手动实现一个简单的vector1.C语言中动态数组的申请与使用1.动态数组的申请使用new和delete使用std::vector 1.std::vector的底层实现2.手动实现一个简单的vector:使用一个指向…

Java设计模式之观察者模式

目录 定义 结构 案例 优点 缺点 使用场景 JDK源码解析 定义 又被称为发布-订阅&#xff08;Publish/Subscribe&#xff09;模式&#xff0c;它定义了一种一对多的依赖关系&#xff0c;让多个观察者对象同时监听某一个主题对象。这个主题对象在状态变化时&#xff0c;会…

iSlide2024一款基于PPT的插件工具包含38个设计辅助功能

根据使用者情况表明iSlide 是一款拥有30W素材的PPT高效设计软件&#xff0c;可提高90%工作效率&#xff0c;现全球已有超过1400万使用者&#xff0c;智能排版原创高品模板可商用图形&#xff0c;真正摆脱PPT的束缚&#xff0c;把精力用在该用的地方。我们都明白islide插件功能特…

PYTHON学习

元组不可修改&#xff1a; 元组支持下标索引。 字符串也是容器&#xff0c;不支持修改。

selenium自动化测试入门 —— 设置等待时间

time.sleep(3) 固定等待3秒 driver.implicitly_wait(10) 隐性的等待&#xff0c;对应全局 WebDriverWait( driver, timeout).until(‘有返回值的__call__()方法或函数’) 显性的等待&#xff0c;对应到元素 一、time.sleep(seconds) 固定等待 import time time.sleep(3) #…

Gopro hero5运动相机格式化后恢复案例

Gopro运动相机以稳定著称&#xff0c;旗下的Hero系列销售全球。下面我们来看一个Hero5格式化后拍了少量素材的恢复案例。 故障存储:64G MicroSD卡 Exfat文件系统 故障现象: 64G的卡没备份数据时做了格式化操作又拍了一条&#xff0c;发现数据没有备份&#xff0c;客户自行使…

Pytorch 文本情感分类案例

一共六个脚本,分别是: ①generateDictionary.py用于生成词典 ②datasets.py定义了数据集加载的方法 ③models.py定义了网络模型 ④configs.py配置一些参数 ⑤run_train.py训练模型 ⑥run_test.py测试模型 数据集https://download.csdn.net/download/Victor_Li_/88486959?spm1…

《研发效能(DevOps)工程师》课程简介(三)丨IDCF

在研发效能领域中&#xff0c;【开发与交付】的学习重点在于掌握高效的开发工具和框架&#xff0c;了解敏捷开发方法&#xff0c;掌握持续集成与持续交付技术&#xff0c;以及如何保证应用程序的安全性和合规性等方面。 由国家工业和信息化部教育与考试中心颁发的职业技术证书…

【多线程】龟兔赛跑

package org.example;public class Race implements Runnable {//胜利者private static String winner;Overridepublic void run() {for(int i0;i<100;i){boolean flag gameOver(i);//如果flag>100,结束比赛if(flag){break;}System.out.println(Thread.currentThread().g…

Vue实现消费清单明细饼图展示

功能 可以进行消费项增删消费额大于500会标红消费金额合计饼图展示消费项 代码 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta name"viewport" content"widthdevice-width, initial-…

U盘显示无媒体怎么办?方法很简单

当出现U盘无媒体情况时&#xff0c;您可以在磁盘管理工具中看到一个空白的磁盘框&#xff0c;并且在文件资源管理器中不会显示出来。那么&#xff0c;导致这种问题的原因是什么呢&#xff1f;我们又该怎么解决呢&#xff1f; 导致U盘无媒体的原因是什么&#xff1f; 当您遇到上…