当前位置: 首页 > news >正文

Synchronized 关键字

在Java中,线程同步使用最多的方法是使用synchronized关键字。每个Java对象都隐含有一把锁,这里称为Java内置锁(或者对象锁、隐式锁)。使用synchronized(syncObject)调用相当于获取 syncObject 的内置锁,所以可以使用内置锁对临界区代码段进行排他性保护。

synchronized 同步方法


synchronized 关键字是Java的保留字,当使用synchronized关键字修饰一个方法的时候,该方法被声明为同步方法,具体的例子如下:

//同步方法
public synchronized void selfplus(){amount++;
}

关键字synchronized的位置处于同步方法的返回类型之前。回到前面的线程安全小实验,现在使用synchronized关键字对临界区代码段进行保护,代码如下:

package com.crazymakercircle.plus;// 省略importpublic class SafePlus{private Integer amount -0://临界区代码段使用synchronized进行保护 public synchronized void selfplus () {amount++;}
}

        再次运行测试用例程序,累加10000次之后,最终的结果不再有偏差,与预期的结果(10000)是相同的。
        在方法声明中设置synchronized同步关键字,保证其方法的代码执行流程是排他性的。任何时间只允许一个线程进入同步方法(临界区代码段),如果其他线程需要执行同一个方法,那么只能等待和排队。

 

synchronized 同步块

        对于小的临界区,我们直接在方法声明中设置synchronized同步关键字,可以避免竞态条件的问题。但是对于较大的临界区代码段,为了执行效率,最好将同步方法分为小的临界区代码段。通过下面这个例子来具体讲述:

public class TwoPlus {    private int sum1 = 0; private int sum2 =0;//同步方法public synchronized void plus(int vall,int val2){//临界区代码段this.sum1 += vall; this.sum2 += va12;}
}

        在以上代码中,临界区代码段包含对两个临界区资源的操作,这两个临界区资源分别为sum1和 sum2。使用synchronized对plus(int vall, int val2)进行同步保护之后,进入临界区代码段的线程拥有sum1和sum2的操作权,并且是全部占用。一旦线程进入,当线程在操作sum1而没有操作sum2时,也将sum2的操作权白白占用,其他的线程由于没有进入临界区,只能看着sum2被闲置而不能去执行操作。

        所以,将synchronized加在方法上,如果其保护的临界区代码段包含的临界区资源(要求是相互独立的)多于一个,就会造成临界区资源的闲置等待,进而会影响临界区代码段的吞吐量、为了提升吞吐量,可以将synchronized关键字放在函数体内,同步一个代码块。synchronized 同步块的写法是:

synchronized (syncObject) //同步块而不是方法
{//临界区代码段的代码块 
}

 

        在synchronized同步块后边的括号中是一个syncObject对象,代表着进入临界区代码段需要获取 syncObject对象的监视锁,或者说将syncObject对象监视锁作为临界区代码段的同步锁。由于每一个Java对象都有一把监视锁,因此任何Java对象都能作为synchronized的同步锁。

        单个线程在synchronized同步块后面的同步锁后,才能进入临界区代码段;反过来说,当一个线程获得syncObject对象的监视锁后,其他线程就只能等待。
使用synchronized同步块对上面的TwoPlus类进行吞吐量的提升改造,具体的代码如下:

public class TwoPlus {private int suml0; private int sum2 =0;private Integer sumllock - new Integer(1); //同步锁一 private Integer sum2Lock = new Integer(2); //同步锁二 public void plus(int val1, int val2){//同步块1synchronized (this.sumlLock){this.sum1 += vall;}//同步块2synchronized(this.sum2Lock){this.sum2 += val2;}}
}

        改造之后,对两个独立的临界区资源sum1 和sum2的加法操作可以并发执行了,在某一个时刻,不同的线程可以对sum1和sum2同时进行加法操作,提升了plus(方法的吞吐量。
        在TwoPlus代码中,由于同步块1和同步块2保护着两个独立的临界区代码段,需要两把不同的 syncObject对象锁,因此TwoPlus代码新加了sum1Lock和sum2Lock两个新的成员属性。这两个属性没有参与业务处理,TwoPlus仅仅利用了sum1Lock 和 sum2Lock的内置锁功能。

        synchronized 方法和synchronized同步块有什么区别呢?总体来说,synchronized方法是一种粗粒度的并发控制,某一时刻只能有一个线程执行该synchronized方法;而synchronized代码块是一种细粒度的并发控制,处于synchronized块之外的其他代码是可以被多个线程并发访问的。在一个方法中,并不一定所有代码都是临界区代码段,可能只有几行代码会涉及线程同步问题。所以synchronized 代码块比synchronized方法更加细粒度地控制了多个线程的同步访问。         synchronized 方法和synchronized代码块有什么联系呢?在Java的内部实现上,synchronized方法实际上等同于用一个synchronized代码块,这个代码块包含同步方法中的所有语句,然后在 synchronized 代码块的括号中传入this关键字,使用this对象锁作为进入临界区的同步锁。

 

        例如,下面两种实现多线程同步的plus方法版本编译成JVM内部字码后结果是一样的。版本一,使用synchronized代码块对方法内部全部代码进行保护,具体代码如下:

public void plus () {synchronized(this) { //对方法内部全部代码进行保护amount++;}
}


版本二,使用synchronized方法对方法内部全部代码进行保护,具体代码如下:

public synchronized void plus() {amount++;
}


综上所述,synchronized方法的同步锁实质上使用了this对象锁,这样就免去了手工设置同步锁的工作。而使用synchronized代码块需要手工设置同步锁。

静态的同步方法

        在Java世界里一切皆对象。Java有两种对象:Object实例对象和Class对象。每个类运行时的类型信息用Class对象表示,它包含与类名称、继承关系、字段、方法有关的信息。JVM将一个类加载入自己的方法区内存时,会为其创建一个Class对象,对于一个类来说其Class对象是唯一的。 Class类没有公共的构造方法,Class对象是在类加载的时候由Java虚拟机调用类加载器中的 defineClass 方法自动构造的,因此不能显式地声明一个Class对象。
        所有的类都是在第一次使用时被动态加载到JVM中的(懒加载),其各个类都是在必需时才加载的。这一点与许多传统语言(如C++)都不同,JVM为动态加载机制配套了一个判定一个类是否已经被加载的检查动作,使得类加载器首先检查这个类的Class对象是否已加载。如果尚未加载,类加载器就会根据类的全限定名查找.class文件,验证后加载到JVM的方法区内存并构造其对应的Class对象。
        普通的synchronized实例方法,其同步锁是当前对象this的监视锁。如果某个synchronized方法是static(静态)方法,而不是普通的对象实例方法,其同步锁又是什么呢?

        下面展示一个使用synchronized关键字修饰static方法的例子,具体如下:

package com.crazymakercircle.plusi
//省略import
public class SafeStaticMethodPlus{ //静态的临界区资源private static Integer amount = 0;//使用synchronized关键字修饰 static方法public static synchronized void selfPlus (){amount++;}
}


        大家都知道,静态方法属于Class实例而不是单个Object实例,在静态方法内部是不可以访
问Object实例的this引用(也叫指针、句柄)的。所以,修饰static方法的synchronized关键字就没有办法获得Object 实例的this对象的监视锁。  

        实际上,使用synchronized关键字修饰static方法时,synchronized的同步锁并不是普通Object   对象的监视锁,而是类所对应的 Class 对象的监视锁。 
        为了以示区分,这里将Object对象的监视锁叫作对象锁,将Class对象的监视锁叫作类锁。当synchronized 关键字修饰static方法时,同步锁为类锁:当synchronized关键字修饰普通的成员方法(非静态方法)时,同步锁为类锁。由于类的对象实例可以有很多,但是每个类只有一个Class实例,因此使用类锁作为synchronized的同步锁时会造成同一个JVM内的所有线程只能互斥地进入临界区段。

//对JVM内的所有线程同步
public static synchronized void selfplus (){//临界区代码
}


        所以,使用synchronized关键字修饰static方法是非常粗粒度的同步机制。
        通过synchronized关键字所抢占的同步锁什么时候释放呢?一种场景是synchronized块(代码块或者方法)正确执行完毕,监视锁自动释放;另一种场景是程序出现异常,非正常退出 synchronized块,监视锁也会自动释放。所以,使用synchronized块时不必担心监视锁的释放问题。

 

 

相关文章:

Synchronized 关键字

在Java中,线程同步使用最多的方法是使用synchronized关键字。每个Java对象都隐含有一把锁,这里称为Java内置锁(或者对象锁、隐式锁)。使用synchronized(syncObject)调用相当于获取 syncObject 的内置锁,所以可以使用内置锁对临界区代码段进行…...

Maven系列第8篇:大型Maven项目,快速按需任意构建

本篇涉及到的内容属于神技能,多数使用maven的人都经常想要的一种功能,但是大多数人都不知道如何使用,废话不多说,上干货。 需求背景 我们需要做一个电商项目,一般都会做成微服务的形式,按业务进行划分&am…...

卷积神经网络(CNN)的组成结构以及其优点

卷积神经网络(Convolutional Neural Network,简称CNN)是一种深度学习模型,主要用于处理具有网格结构的数据,如图像和视频。它的结构包含以下几个关键组件: 卷积层(Convolutional Layer&#xff…...

[③ADRV902x]: Digital Filter Configuration(接收端)

前言 本篇博客主要总结了ADRV9029 Rx接收端链路中各个滤波器的配置。配置不同的滤波器系数以及不同的参数,可以对输入的数字信号灵活得做decimation处理,decimation信号抽取,就是降低信号采样率的过程。 Receiver Signal Path 下图为接收端…...

企业安全—DevSecOps概述详情

0x00 前言 SDL存在的问题在于体量过于庞大,不利于快速进行适配和进行,所以就有了DevSecOps,实际上是因为敏捷开发也就是DevOps的推进,并且坐上了云服务模式的火车,所以这一系列的东西都开始普及。DevSecOps作为DevOps…...

数据结构与算法(十):动态规划与贪心算法

参考引用 Hello 算法 Github:hello-algo 1. 动态规划算法 动态规划将一个问题分解为一系列更小的子问题,并通过存储子问题的解来避免重复计算,从而大幅提升时间效率 问题:给定一个共有 n 阶的楼梯,你每步可以上 1 阶或…...

【C++代码】安排行程,N皇后,解数独--代码随想录

题目:重新安排行程 给你一份航线列表 tickets ,其中 tickets[i] [fromi, toi] 表示飞机出发和降落的机场地点。请你对该行程进行重新规划排序。所有这些机票都属于一个从 JFK(肯尼迪国际机场)出发的先生,所以该行程必…...

SpringCloud Alibaba【二】nacos

nacos配置与使用 nacos初步使用nacos安装与配置创建命名空间 nacos使用与配置创建新项目作为父项目 创建nacos服务端项目pom.xmlapplication.yml启动类 创建nacos客户端项目pom.xml application.yml启动类 启动测试 nacos配置负载均衡改造生产者nacos-provider-projectcontroll…...

C++中的fsanitize指令

一个集成在 gcc、clang 编译器中的编译指令&#xff0c;可以有效测试程序中的一些诸如数组越界、未定义行为等情况。 举个例子&#xff1a; #include <bits/stdc.h> using namespace std;const int maxn2e55,mxr1e5,maxm1e75; int head[maxn],nxt[maxn],to[maxn],f[max…...

【AI视野·今日Robot 机器人论文速览 第五十八期】Thu, 19 Oct 2023

AI视野今日CS.Robotics 机器人学论文速览 Thu, 19 Oct 2023 Totally 25 papers &#x1f449;上期速览✈更多精彩请移步主页 Daily Robotics Papers InViG: Benchmarking Interactive Visual Grounding with 500K Human-Robot Interactions Authors Hanbo Zhang, Jie Xu, Yuch…...

Java截取(提取)子字符串(substring()),Java分割字符串(split())

在 String 中提供了两个截取字符串的方法&#xff0c;一个是从指定位置截取到字符串结尾&#xff0c;另一个是截取指定范围的内容。下面对这两种方法分别进行介绍。 1. substring(int beginIndex) 形式 此方式用于提取从索引位置开始至结尾处的字符串部分。调用时&#xff0c…...

从厨房间到股市:家庭主妇的华美转身

我一直是一个安于现状的家庭主妇。生活中&#xff0c;我热爱烹饪、园艺和照顾家人&#xff0c;但我也渴望能有更多的自我实现和价值感。在机缘巧合下&#xff0c;我接触到了卓扬网&#xff0c;一个专业的股票投资平台。从那刻起&#xff0c;我的人生发生了翻天覆地的变化。 初…...

Oracle 数据库的锁排查方法

关键字 oracle lock 问题描述 Oracle 数据库上锁问题如何排查 解决问题思路 准备数据 create table lock_test(name varchar(10),age varchar(10));insert into lock_test values(ff,10); insert into lock_test values(yy,20); insert into lock_test values(ll,30);Orac…...

混合精度训练原理之float16和float32数据之间的互相转换

混合精度训练原理之float16和float32数据之间的互相转换 本篇文章参考&#xff1a;全网最全-混合精度训练原理 上述文章已经讲解的比较详细&#xff0c;本文只是从数值角度分析&#xff1a; 1. float32转入float16的精度误差 2. 在深度学习的混精度训练当中&#xff0c;当参数…...

网络协议--ICMP:Internet控制报文协议

6.1 引言 ICMP经常被认为是IP层的一个组成部分。它传递差错报文以及其他需要注意的信息。ICMP报文通常被IP层或更高层协议&#xff08;TCP或UDP&#xff09;使用。一些ICMP报文把差错报文返回给用户进程。 ICMP报文是在IP数据报内部被传输的&#xff0c;如图6-1所示。 ICMP…...

《红蓝攻防对抗实战》三.内网探测协议出网之HTTP/HTTPS协议探测出网

目录 一. 在 Windows 操作系统中探测 HTTP/HTTPS 出网 1. Bitsadmin 命令 2.Certuil 命令 2.Linux系统探测HTTP/HTTPS出网 1.Curl命令 2.Wget命令 对目标服务器探测 HTTP/HTTPS 是否出网时&#xff0c;要根据目标系统类型执行命令&#xff0c;不同类型的操作系统使用的探…...

【Win11】系统重装教程(最新最详细)

目录 一.简介 二.用U盘制作PE系统 三、安装系统 软件&#xff1a;Windows 11版本&#xff1a;21H2语言&#xff1a;简体中文大小&#xff1a;5.14G安装环境&#xff1a;PE系统&#xff0c;至少7代处理器硬件要求&#xff1a;CPU2.0GHz 内存4G(或更高&#xff09;下载通道①丨…...

如何构建一个外卖微信小程序

随着外卖行业的不断发展&#xff0c;越来越多的商家开始关注外卖微信小程序的开发。微信小程序具有使用方便、快速上线、用户覆盖广等优势&#xff0c;成为了商家们的首选。 那么&#xff0c;如何快速开发一个外卖微信小程序呢&#xff1f;下面就让我们来看看吧&#xff01; 首…...

小知识(5) el-table行样式失效问题

一、实现效果 子级呈现不同颜色去区分 二、最初代码 tips: 我这里使用的vue3 elementplus <el-table :row-class-name"tableRowClassName" >... </el-table>function tableRowClassName({ row, rowIndex }) {if (row.children.length 0) {return …...

【Docker】Docker数据的存储

默认情况下&#xff0c;在运行中的容器里创建的文件&#xff0c;被保存在一个可写的容器层里&#xff0c;如果容器被删除了&#xff0c;则对应的数据也随之删除了。 这个可写的容器层是和特定的容器绑定的&#xff0c;也就是这些数据无法方便的和其它容器共享。 Docker主要提…...

vue+elementUI+springboot实现文件合并前端展示文件类型

项目场景&#xff1a; element的table上传文件并渲染出文件名称点击所属行可以查看文件,并且可以导出合并文件,此文章是记录合并文档前端展示的帖子 解决方案&#xff1a; 后端定义三个工具类 分别是pdf,doc和word的excle的目前我没整 word的工具类 package com.sc.modules…...

基于springboot的校园社团信息系统的设计与实现

其他源码获取可以看首页&#xff1a;代码老y 个人简介&#xff1a;专注于毕业设计项目定制开发&#xff1a;springbootvue系统&#xff0c;Java微信小程序&#xff0c;javaSSM系统等技术开发&#xff0c;并提供远程调试部署、代码讲解、文档指导、ppt制作等技术指导。源码获取&…...

Next.js+prisma开发一

1.初始化Next.js项目 #按版本安装 npx create-next-app13.4.5 如果最新版本 执行&#xff1a;npx create-next-applatest2. 安装Prima和客户端 npm install prisma --save-dev npm install prisma/client3.初始化Prisma&#xff0c;以SQLit举例 # 初始化 Prisma 并配置 SQLi…...

让敏感数据在流转与存储中始终守护在安全范围

在企业数字化运营浪潮中&#xff0c;企业内部应用服务器面临着非法访问、数据泄露等风险&#xff0c;如何全面守护应用服务器文件安全&#xff0c;让敏感数据在流转与存储中始终守护在安全范围&#xff1f; 服务器白名单让数据流转安全又高效 天 锐 蓝盾的服务器白名单功能既…...

飞云智能波段主图+多空短线决策副图指标,组合操盘技术图文解说

如上图&#xff0c;组合指标&#xff1a;主图-飞云智能波段&#xff0c;红线上红色K线标记&#xff0c;波段做多.副图指标-多空短线决策&#xff0c;跟踪做短线&#xff0c;红柱做多&#xff0c;绿柱短线卖出或做空。 实战操作中&#xff0c;我们在主图红色线支撑上红色K线出现…...

Linux: network: switch:arp cache更新规则 [chatGPT]

文章目录 介绍概念普通包带有不同的mac,是否更新arp cache?普通包带有相同的mac,是否刷新 aging timeswitch是否会主动学习介绍 关于arp cache在switch侧的行为。有很多问题需要理解。 概念 HP L3 - IP Services Configuration Guide 文档里有写:dynamic arp entry的解说…...

A*算法实现原理以及实现步骤(C++)

算法原理&#xff1a; A*算法是一种启发式搜索算法&#xff0c;用于在图中寻找最短路径。它结合了Dijkstra算法的确保最短路径的优点和贪心最佳优先搜索的高效性。其核心在于使用一个评估函数&#xff1a; f(n) g(n) h(n) 其中&#xff1a; - g(n) 表示从起点到节点n的实际代…...

国产linux系统(银河麒麟,统信uos)使用 PageOffice在线编辑word文件保存数据同时保存文件

在实际应用中&#xff0c;例如在线签订合同的时候&#xff0c;合同的签订日期&#xff0c;合同号等等这些信息既要保存到数据库&#xff0c;合同签订后又要将整个合同文件保存起来。这时候就需要用到PageOffice的保存数据区域数据的同时保存整个文件的功能。 后端代码 后端打…...

vue2中的render函数

<script> export default {components: {},name: "renderElems",render (h, context) {return this.$attrs.vnode;},updated() {} } </script> <style scoped> </style>分析一下上面.vue组件&#xff1a; 组件结构&#xff1a; 这是一个非…...

吴恩达MCP课程(5):research_server_prompt_resource.py

代码 import arxiv import json import os from typing import List from mcp.server.fastmcp import FastMCPPAPER_DIR "papers"# Initialize FastMCP server mcp FastMCP("research")mcp.tool() def search_papers(topic: str, max_results: int 5) …...