java的synchronized 原理及功能

简介:

Java中的synchronized关键字是一种同步机制,用于控制多个线程对共享资源的访问。

原理:

在Java锁有一个内部锁 Intrinsic Lock,也称为监视器锁或管程锁,每个Java对象都有一个关联的监视器锁,隐式锁通常是由编程语言、运行时库或者虚拟机自动管理的,不需要程序员手动调用锁的获取和释放方法,使用较为简便,并且 隐式锁通常会在不需要的时候自动释放,从而减少了由于忘记释放锁而导致的死锁等问题的风险。通过synchronized关键字来获取和释放对象的监视器锁。

使用:

实例方法加锁

使用synchronized修饰方法时,它将锁定整个方法,即使方法中有多个代码块,也只有一个线程可以进入该方法。

public class AccountingSync implements Runnable {//共享资源(临界资源)static int i=0;/*** synchronized 修饰实例方法*/public synchronized void increase(){i++;}@Overridepublic void run() {for(int j=0;j<1000000;j++){increase();}}public static void main(String[] args) throws InterruptedException {AccountingSync instance = new AccountingSync();Thread t1=new Thread(instance);Thread t2=new Thread(instance);t1.start();t2.start();t1.join();t2.join();System.out.println(i);}
}

运行上述代码,打印出了我们预期的结果 2000000,由于 ++ 操作是非线程安全的,所以这一结果表明我们加锁是成功的。 两个线程是通过同一个实例 instance 运行的,所以他们通过这个实例的同一把锁实现了线程的并发安全,而下面的代码就将无法得到预期的结果:

public class AccountingSyncBad implements Runnable {static int i=0;public synchronized void increase(){i++;}@Overridepublic void run() {for(int j=0;j<1000000;j++){increase();}}public static void main(String[] args) throws InterruptedException {//new新实例Thread t1 = new Thread(new AccountingSyncBad());//new新实例Thread t2 = new Thread(new AccountingSyncBad());t1.start();t2.start();//join含义:当前线程A等待thread线程终止之后才能从thread.join()返回t1.join();t2.join();System.out.println(i);}
}

运行结果打印出了 1452317,这是因为两个线程分别运行在两个 new 出来的不同的实例中,这意味着他们有着两个不同的实例对象锁,因此他们各自对 increase 方法加锁是无法实现锁的作用的。

static 方法加锁:

与实例方法不同,static 方法是无法获取到实例对象的 this 引用的,因此对 static 方法加锁,锁定的目标就是 class 对象,所有使用该类的线程都将获取到同一把锁。

public class AccountingSyncBad implements Runnable {static int i=0;public synchronized void increase(){i++;}@Overridepublic void run() {for(int j=0;j<1000000;j++){increase();}}public static void main(String[] args) throws InterruptedException {//new新实例Thread t1 = new Thread(new AccountingSyncBad());//new新实例Thread t2 = new Thread(new AccountingSyncBad());t1.start();t2.start();//join含义:当前线程A等待thread线程终止之后才能从thread.join()返回t1.join();t2.join();System.out.println(i);}
}

此时运行上述代码可以得到预期的加锁效果,虽然我们通过 new 传入不同的实例,但是因为 static 方法上的 synchronized 关键字是通过对 class 对象加锁,两个线程仍然是在竞争同一把锁。

synchronized 同步代码块

编写 synchronized 同步代码块是最灵活的一种加锁方式了,他不仅可以实现上述两种加锁方式的功能,还可以实现更加精细化的加锁控制。 在某些情况下,我们编写的方法体可能比较大,也可能存在一些比较耗时的操作,而需要同步的代码又只有一小部分,如果直接对整个方法进行同步操作,可能会得不偿失,此时我们可以使用同步代码块的方式对需要同步的代码进行包裹,这样就无需对整个方法进行同步操作了。

public class AccountingSync implements Runnable{static AccountingSync instance = new AccountingSync();static int i=0;@Overridepublic void run() {//省略其他耗时操作....//使用同步代码块对变量i进行同步操作,锁对象为instancesynchronized(instance){for(int j=0;j<1000000;j++){i++;}}}public static void main(String[] args) throws InterruptedException {Thread t1=new Thread(instance);Thread t2=new Thread(instance);t1.start();t2.start();t1.join();t2.join();System.out.println(i);}
}

上述代码我们通过对代码执行的一部分加锁,实现了上述对实例方法加锁的相同功能,我们通过对类的 static 成员 instance 加锁,实现并发安全性。 常用的使用方法有对 this 引用加锁和对 class 对象加锁:

//this,当前实例对象锁
synchronized(this){for(int j=0;j<1000000;j++){i++;}
}//class对象锁
synchronized(AccountingSync.class){for(int j=0;j<1000000;j++){i++;}
}

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

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

相关文章

HarmonyOS NEXT端云一体化工程目录结构

视频课程学习报名入口:HarmonyOS NEXT端云一体化开发 端云一体化开发工程由端开发工程(Application)和云开发工程(CloudProgram)两大核心模块构成。 1)端开发工程目录结构 端开发工程主要用于开发应用端侧的业务代码,通用云开发模板的端开发工程目录结构如下图所示: …

普通用户的服务器连接与模型部署相关记录

普通用户的服务器连接与模型部署相关记录 一、从登录到使用自己的conda 1.账号登陆&#xff1a; ssh xxx172.31.226.236 2.下载与安装conda&#xff1a; 下载conda&#xff1a; wget -c https://repo.anaconda.com/archive/Anaconda3-2023.03-1-Linux-x86_64.sh 安装con…

亲测有效!OGG 创建抽取进程报错 OGG-08241,如何解决?

前言 今天在测试 OGG 一个功能的时候&#xff0c;需要重新初始化 oggca&#xff0c;所以重装了一下 OGG。重建完之后重新添加抽取进程报错&#xff0c;一直无法添加成功&#xff1a; 经过一翻分析&#xff0c;找到了解决方案&#xff0c;本文记录一下解决过程。 问题描述 OG…

Docker构建 Dify 应用定时任务助手

概述 Dify 定时任务管理工具是一个基于 GitHub Actions 的自动化解决方案&#xff0c;用于实现 Dify Workflow 的定时执行和状态监控。无需再为缺乏定时任务支持而感到困扰&#xff0c;本工具可以帮助设置自动执行任务并获取实时通知&#xff0c;优化你的工作效率。 注意&…

ubuntu24.04+RTX5090D 显卡驱动安装

初步准备 Ubuntu默认内核太旧&#xff0c;用mainline工具安装新版&#xff1a; sudo add-apt-repository ppa:cappelikan/ppa sudo apt update && sudo apt full-upgrade sudo apt install -y mainline mainline list # 查看可用内核列表 mainline install 6.13 # 安装…

网络爬虫(Web Crawler)详解

网络爬虫(Web Crawler)详解 1. 基本概念与核心目标 定义: 网络爬虫是一种自动化的程序,通过HTTP协议访问网页,提取并存储数据(如文本、链接、图片),并根据策略递归访问新链接。核心目标: 数据采集:抓取特定网站或全网公开数据。索引构建:为搜索引擎提供页面内容(如…

大模型如何助力数学可视化?

大家好&#xff0c;我是 i 学习的老章 在数学学习和教学中&#xff0c;将抽象概念可视化对于理解至关重要。Manim 是一个强大的数学动画引擎&#xff0c;由著名数学科普视频作者 3Blue1Brown 开发并广为人知。 老章较早之前就介绍过 manim&#xff1a;B 站上爆红的数学视频&a…

Oracle基础知识(二)

目录 1.聚合函数 2.COUNT(1)&COUNT(*)&COUNT(字段)区别&#xff08;面试常问&#xff09; 3.分组聚合——group by 4.去重&#xff1a;DISTINCT 、GROUP BY 5.聚合函数的过滤HAVING 6.oracle中having与where的区别 (面试常问) 7.ROUND与TRUNC函数 8.ROLLUP上卷…

DTAS 3D多约束装配助力悬架公差分析尺寸链计算:麦弗逊/双叉臂/多连杆/H臂一网打尽

摘要&#xff1a;汽车四轮定位参数与悬架密切相关。汽车悬架对于车辆的行驶性能、安全性和舒适性至关重要。DTAS 3D提供了各类型悬架的公差仿真分析方法。 关键字&#xff1a;DTAS 3D、前后悬架、公差仿真分析、 运动耦合 一、悬架公差分析综述 悬架是车身&#xff08;或车架…

Serverless爬虫架构揭秘:动态IP、冷启动与成本优化

一、问题背景&#xff1a;旧技术的瓶颈 在传统爬虫架构中&#xff0c;我们通常部署任务在本地机器或虚拟机中&#xff0c;搭配定时器调度任务。虽然这种方式简单&#xff0c;但存在以下明显缺陷&#xff1a; 固定IP易被封禁&#xff1a;目标网站如拼多多会通过IP频率监控限制…

设备预测性维护的停机时间革命:中讯烛龙如何用AI重构工业设备管理范式

在工业4.0的智能化浪潮中&#xff0c;非计划停机每年吞噬企业3%-8%的产值。中讯烛龙预测性维护系统通过多模态感知矩阵分布式智能体的创新架构&#xff0c;实现设备健康管理的范式跃迁&#xff0c;帮助制造企业将停机时间压缩70%以上。本文将深度解析技术实现路径与行业级实践方…

Java面试攻略:从Spring Boot到微服务架构的深入探讨

Java面试攻略&#xff1a;从Spring Boot到微服务架构的深入探讨 场景设定 在一家知名互联网大厂的会议室里&#xff0c;资深面试官王老师正在对一位求职者谢飞机进行技术面试。谢飞机是一位幽默风趣的程序员&#xff0c;他的回答有时让人捧腹大笑。 第一轮&#xff1a;核心技…

LlamaIndex

1、大语言模型开发框架的价值是什么? SDK:Software Development Kit,它是一组软件工具和资源的集合,旨在帮助开发者创建、测试、部署和维护应用程序或软件。 所有开发框架(SDK)的核心价值,都是降低开发、维护成本。 大语言模型开发框架的价值,是让开发者可以更方便地…

【linux命令】git命令简单使用

git命令简单使用 1. 将代码下载到到本地2. 查看分支是否正确3. 将工作目录中的变更添加到暂存区&#xff0c;为下一次提交做准备4. 提交更改&#xff0c;添加提交信息5. 将本地的提交推送到远程仓库6.从远端仓库拉取分支代码7.查看修改日志8. 解决冲突 1. 将代码下载到到本地 …

debian系统redis-dump安装

1. ​Ruby 环境​ Redis-dump 是一个 Ruby 工具&#xff0c;需先安装 Ruby 和 RubyGems。 安装命令​&#xff1a; sudo apt update sudo apt install ruby-full build-essential[roota29d39f5fd10:/opt/redis-dump/bin# apt install ruby-full build-essential Reading pac…

微软押注“代理式AI网络”:一场重塑软件开发与工作方式的技术革命

在 2025 年 Build 开发者大会上&#xff0c;微软正式发布了其面向“开放代理式网络&#xff08;Open Agentic Web&#xff09;”的宏大战略&#xff0c;推出超过 50 项 AI 相关技术更新&#xff0c;涵盖 GitHub、Azure、Windows 和 Microsoft 365 全线产品。这一系列更新的核心…

【音频】wav文件如何解析编码格式(压缩格式)?

要确定一个WAV文件的编码格式&#xff0c;可以通过以下几种方法实现&#xff0c;包括使用操作系统自带工具、专业音频软件或编程解析文件头信息。以下是详细说明&#xff1a; 一、通过文件属性查看&#xff08;Windows/macOS&#xff09; 1. Windows系统 步骤&#xff1a; 右…

算法打卡第三天

10.长度最小的子数组 &#xff08;力扣209题&#xff09; 给定一个含有 n 个正整数的数组和一个正整数 target 。 找出该数组中满足其总和大于等于 target 的长度最小的 子数组 [numsl, numsl1, ..., numsr-1, numsr] &#xff0c;并返回其长度**。**如果不存在符合条件的子…

数字电子技术基础(六十二)——使用Multisim软件绘制边沿触发的D触发器和JK触发器

1 使用Mulitism软件模拟时钟触发的D触发器 D触发器是一种基本的数字电路存储元件&#xff0c;它在时钟信号的边沿将输入数据D传递到输出Q。下面开始使用Multisim软件来模拟时钟触发的D触发器。 器件选择&#xff1a; 触发器选择&#xff1a;在组选项栏中点击Misc Digital&am…

自动获取新版本 js 静态文件

场景 代码里有静态js文件&#xff0c;发布一个版本1.0在真实环境&#xff0c;再修改重新发布2.0&#xff0c;用户如何得到新版本&#xff1f; 方法 一、文件名哈希策略&#xff08;最推荐&#xff09; 通过构建工具为文件生成唯一哈希值&#xff0c;使每次更新后的文件名不同…