java线程锁synchronized的几种情况

一、对象方法锁

1、成员方法加锁

         同一个对象成员方法有3个synchronized修饰的方法,通过睡眠模拟业务操作

    public class   CaseOne {public   synchronized   void  m1(){try { TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e) { e.printStackTrace();}System.out.println(SDF.format(new Date())+"------------>m1");}public   synchronized   void  m2()  {try { TimeUnit.SECONDS.sleep(2); } catch (InterruptedException e) { e.printStackTrace();}System.out.println(SDF.format(new Date())+"------------>m2");}public   synchronized   void  m3()  {try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace();}System.out.println(SDF.format(new Date())+"------------>m3");}}
    private final static SimpleDateFormat  SDF = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");private final static ExecutorService POOL = Executors.newFixedThreadPool(4);public static void main(String[] args) {CaseOne caseOne = new CaseOne();System.out.println(SDF.format(new Date())+"------------>start");POOL.execute(caseOne::m1);POOL.execute(caseOne::m2);POOL.execute(caseOne::m3);}

        运行结果:

        通过运行结果可以看出,三个业务方法,执行完成总共花费了6s,虽然使用了多线程,这三三个方法其实是串行作业的,因此可得出一下结论:   

        同一个对象的不同方法加synchronized修饰,只要其中一个方法抢到锁,其他被synchronized修饰的方法都互斥,本质是对象上锁。

2、成员方法不加锁

    public class   CaseTwo {public   synchronized   void  m1(){try { TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e) { e.printStackTrace();}System.out.println(SDF.format(new Date())+"------------>m1");}public    void  m2()  {try { TimeUnit.SECONDS.sleep(2); } catch (InterruptedException e) { e.printStackTrace();}System.out.println(SDF.format(new Date())+"------------>m2");}public   synchronized   void  m3()  {try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace();}System.out.println(SDF.format(new Date())+"------------>m3");}}
        CaseTwo caseTwo = new CaseTwo();System.out.println(SDF.format(new Date())+"------------>start");POOL.execute(caseTwo::m1);POOL.execute(caseTwo::m2);POOL.execute(caseTwo::m3);

          运行结果:

      三个业务方法执行完成总共花费了4s,结合第一个案例可以得出以下结论:

      同一个对象的不同方法加synchronized,其中加锁方法和不加锁的成员方法没有竞争关系,不产生互斥。

3、不同对象方法锁

        案例1和案例2研究的是同一个的对象,加锁和不加锁的情况,下面来研究不同对象的情况。

    public static class   CaseThree {private final String   name;public CaseThree(String name) {this.name = name;}public   synchronized   void  m1(){try { TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e) { e.printStackTrace();}System.out.println(SDF.format(new Date())+  " "+this.name +"------------>m1");}}
        CaseThree caseThree1 = new CaseThree("caseThree1");CaseThree caseThree2 = new CaseThree("caseThree2");System.out.println(SDF.format(new Date())+" "+"------------>start");POOL.execute(caseThree1::m1);POOL.execute(caseThree2::m1);

         运行结果:

      由执行结果可以看出,对象caseThree1 和对象caseThree12调用同一个方法,同时执行完成,可以得出以下结论:

       不同的对象执行同一个成员方法,没有竞争关系,加锁方法不互斥。

二、类方法加锁

         下面研究一下一个类型static修饰的静态方法加锁

1、静态方法锁

    public static class   CaseFour {public  static synchronized   void  m1(){try { TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e) { e.printStackTrace();}System.out.println(SDF.format(new Date())+  " "+"------------>m1");}public  static synchronized   void  m2(){try { TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e) { e.printStackTrace();}System.out.println(SDF.format(new Date())+  " "+"------------>m2");}}
        System.out.println(SDF.format(new Date())+" "+"------------>start");POOL.execute(CaseFour::m1);POOL.execute(CaseFour::m2);

  

           由执行的结果可以得出以下结论:

           同一个类的不同静态方法之间存在竞争关系,先抢到锁的先执行。

2、不同对象静态方法锁

    public static class   CaseFive {public  static synchronized   void  m1(String name){try { TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e) { e.printStackTrace();}System.out.println(SDF.format(new Date())+  " "+name+"------------>m1");}}
        CaseFive caseFive1 = new CaseFive();CaseFive caseFive2 = new CaseFive();System.out.println(SDF.format(new Date())+" "+"------------>start");POOL.execute(()->caseFive1.m1("caseFive1"));POOL.execute(()->caseFive2.m1("caseFive2"));

         由运行结果可以得到以下结论:

         同一个类的不同对象调用同一个静态方法,存在竞争关系,会产生互斥。

3、类方法锁和成员方法锁

   ◆场景一:

    public static class   CaseSix {public  static synchronized   void  m1(){try { TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e) { e.printStackTrace();}System.out.println(SDF.format(new Date())+  " "+"------------>m1");}public  synchronized   void  m2(){try { TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e) { e.printStackTrace();}System.out.println(SDF.format(new Date())+  " "+"------------>m2");}}
      CaseSix caseSix = new CaseSix();System.out.println(SDF.format(new Date())+" "+"------------>start");POOL.execute(()->caseSix.m1());POOL.execute(()->caseSix.m2());

        由执行结果可得出以下结论:

   

       同一个类的静态方法和成员方法加锁,同一个对象同时调用,会场生竞争关系,先抢到锁的先执行。

  ◆场景二:

       CaseSix caseSix1 = new CaseSix();CaseSix caseSix2 = new CaseSix();System.out.println(SDF.format(new Date())+" "+"------------>start");POOL.execute(()->caseSix1.m1());POOL.execute(()->caseSix2.m2());

   

         由运行结果可知:

        同一个类的不同对象,分别调用静态类和成员方法,不产生竞态关系。

三、线程锁总结

        类方法做是在类加载过程中已经打上标记了,类信息存储在jvm的常量池中,而对象的方法锁是在运行动态确定的,因此类方法锁和不同的对象成员方法锁之间不存在竞争关系。在并发情景,能用无锁的数据块就不要用锁,能锁区块,就不要锁整个方法体,能锁对象就不要用类锁。

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

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

相关文章

ChIP项目文章CMI(IF=24.1)|IRF1激活可促进辐射诱导的细胞死亡和炎症反应

2024年6月7日,四川大学张舒羽教授团队在Cellular & Molecular Immunology(IF24.1)期刊上发表了题为“Chaperone-and PTM-mediated activation of IRF1 tames radiation-induced cell death and inflammation response”的文章&#xff0c…

Flexcel学习笔记

1.引用的单元 FlexCel.Core 始终需要使用的一个单元。 多系统运行时。{$IFDEF LINUX}SKIA.FlexCel.Core{$ELSE}{$IFDEF FIREMONKEY}FMX.FlexCel.Core{ $ELSE}VCL.FlexCel.Core{$ENDIF}{$ENDIF} FlexCel.XlsAdapter这是FlexCel的xls/x引擎。如果您正在处理xls或xlsx文件&#x…

搭建邮局服务器的配置步骤?如何管理协议?

搭建邮局服务器需要考虑的安全措施?怎么搭建服务器? 在现代互联网环境中,电子邮件是重要的沟通工具。为了保证信息传递的稳定性和安全性,许多企业选择自行搭建邮局服务器。AokSend将详细介绍搭建邮局服务器的配置步骤&#xff0c…

parquet介绍

概述 Apache Parquet 是一种开源的列式数据文件格式,旨在实现高效的数据存储和检索。它提供高性能压缩和编码方案(encoding schemes)来批量处理复杂数据,并且受到许多编程语言和分析工具的支持。 parquet-format parquet-format 存储库托管 Apache Pa…

ELK优化

ELK优化可以从以下几个方面进行: linux内核优化JVM优化ES配置优化架构优化(filebeat/fluentd代替logstash、加入kafka做消息队列) ES 作为日志存储时的特性: 高并发写读少接受 30 秒内的延时可容忍部分日志数据丢失 Logstash优…

如何配置yolov10环境?

本文介绍如何快速搭建起yolov10环境,用于后续项目推理、模型训练。教程适用win、linux系统 yolo10是基于yolo8(ultralytics)的改进,环境配置跟yolo8几乎一模一样。 目录 第1章节:创建虚拟环境 第2章节:…

【debug】keras使用基础问题

keras使用基础问题 一、下载报错报错详情解决方式忽略ssl检查提前将数据或者包下载到本地 参考 一、下载报错 报错详情 1、下载数据报错 (x_train, y_train_cats), (x_test, y_test_cats) cifar10.load_data()报错信息 Exception: URL fetch failure on https://www.cs.tor…

linux中,nohup ... ,改变输出目录

在Linux中,使用nohup命令结合&来在后台运行java -jar xxx.jar命令时,实际上每个nohup命令都会将其标准输出(stdout)和标准错误输出(stderr)重定向到一个名为nohup.out的文件中,除非你明确指…

Tita的OKR:最新20个HR人力资源OKR案例

OKR是一个目标设定框架,可以提高员工的参与度,同时帮助人们专注于最重要的事情。 然而,OKR最大的挑战之一是设定正确的目标,我与很多人力资源专业人士交谈过,他们证明他们的OKR并不完美。 这就是为什么我们收集了最佳…

git-打包指定提交文件.sh

#!/bin/bash # windows :git bash here read -p "请工程路径: " projdir cd $projdir read -p "请输入提交ID(至少7位): " select # latest$(git rev-parse HEAD) latest$(git rev-parse --short HEAD) # set latest$(git rev-parse HEAD) ech…

水文:CBA业务架构师

首先, 我们来了解一下什么是CBA业务架构师? CBA业务架构师认证是由业务架构师公会(Business Architecture Guild)授予的一种专业认证。标志着证书持有者已经掌握了业务架构的核心技能和知识,能够在实际工作中熟练运用业务架构技术和框架&…

Windows 安装Zookeeper

安装 下载地址:Apache ZooKeeper 我下载的版本:zookeeper-3.4.12 下载后,解压 配置 1、 在D:\zookeeper-3.4.12文件夹中创建一个“data”文件夹和“log”文件夹 2、 复制zoo_sample.cfg,改名:zoo.cfg 修改zoo.c…

Jetson-AGX-Orin 安装ROS2

Jetson-AGX-Orin 安装ROS2 确保Orin能够上网 1、安装依赖 sudo apt update sudo apt install curl gnupg2 lsb-release2、添加源 sudo curl -sSL https://raw.githubusercontent.com/ros/rosdistro/master/ros.key -o /usr/share/keyrings/ros-archive-keyring.gpgecho &q…

【C++课程学习】:new和delete为什么要配套使用,new,delete和malloc,free的比较

🎁个人主页:我们的五年 🔍系列专栏:C课程学习 🎉欢迎大家点赞👍评论📝收藏⭐文章 目录 🎡1.new,delete和malloc,free的区别: ⌚️相同点&…

Java的SpringBoot项目中为什么要注入接口XxxService而不是具体的实现类XxxServiceImpl

Java的SpringBoot项目中为什么要注入接口XxxService而不是具体的实现类XxxServiceImpl 在 Java 中,通常建议面向接口编程。注入一个接口而不是具体的实现类有以下几个好处: **解耦:**通过注入接口,实现了服务的调用者&#xff08…

“删错文件后如何高效挽救?两大恢复策略全解析“

在数字化日益深入生活的今天,数据已成为我们工作、学习和娱乐不可或缺的一部分。然而,删错文件的经历却如同数字世界中的一场“小插曲”,不经意间就可能让我们陷入数据丢失的困境。无论是误触删除键、清空回收站,还是软件故障导致…

GCN-LSTM实现时空预测

简介:现有的预测模型越来考虑时间和空间的相关性,统称为时空预测。这种预测模型往往比简单的序列模型(例如RNN、LSTM、GRU及其变体)、Transformer等效果更好。我使用Keras实现了该GCN-LSTM代码,因为Keras相比于torch更容易入手和理解。我实现了一个基于Keras的GCN网络层,…

Linux 宝塔常用命令教程

一、引言 在 Linux 服务器管理中,宝塔面板是一款非常实用的工具。然而,了解一些相关的命令可以让我们在特定情况下更高效地进行操作和管理。本文将为您介绍一些常用的 Linux 宝塔相关命令。 二、安装宝塔面板 首先,如果您还未安装宝塔面板…

数据结构(其一)--基础知识篇

目录 1. 数据结构三要素 1.1 数据结构的运算 1.2 数据结构的存储结构 2. 数据类型,抽象数据类型 3. 算法 3.1 时间复杂度T(n) 3.2 空间复杂度 1. 数据结构三要素 1.1 数据结构的运算 即,增删改查 1.2 数据结构的存储结构 2. 数据类型&#xff0…

企业微信群发限制的背后逻辑,一文读懂!

在数字化营销日益盛行的今天,企业微信作为一款专为企业设计的通讯与办公工具,凭借其与微信的无缝对接和丰富的功能,成为了众多企业开展私域流量运营的重要平台。然而,在使用企业微信的群发功能时,用户往往会遇到一定的…