同步代码块synchronized的使用与解析

2023-11-06

Java 同步块(synchronized block)用来标记方法或者代码块是同步的。Java同步块用来避免竞争。本文介绍以下内容:

  • Java同步关键字(synchronzied)
  • 实例方法同步
  • 静态方法同步
  • 实例方法中同步块
  • 静态方法中同步块
  • Java同步示例

Java同步关键字synchronized

Java中的同步代码块用synchronized标记。同步代码块在Java中是同步在某个对象上。所有同步在一个对象上的同步代码块在同一时刻只能被一个线程进入操作。所有其他等待进入该同步块的线程将会被阻塞,直到执行该同步块的线程退出。

有四种不同的同步块:

  • 实例方法
  • 静态方法
  • 实例方法中的同步块
  • 静态方法中的同步块

上述代码块都同步在不同的对象上。实际需要那种同步块视具体情况而定。

实例方法同步

下面是一个同步的实例方法:

 public synchronized void add(int value){
this.count += value;
 }

注意在方法声明中同步(synchronized )关键字。这告诉Java该方法是同步的。

Java实例方法同步是同步在拥有该方法的对象上。这样,每个实例其方法同步都同步在不同的对象上,即该方法所属的实例。只有一个线程能够在实例方法同步块中运行。如果有多个实例存在,那么一个线程一次可以在一个实例同步块中执行操作。一个实例一个线程。

静态方法同步

静态方法同步和实例方法同步方法一样,也使用synchronized 关键字。Java静态方法同步如下示例:

public static synchronized void add(int value){
 count += value;
 }

同样,这里synchronized 关键字告诉Java这个方法是同步的。

静态方法的同步是指同步在该方法所在的类对象上。因为在Java虚拟机中一个类只能对应一个类对象,所以同时只允许一个线程执行同一个类中的静态同步方法。

对于不同类中的静态同步方法,一个线程可以执行每个类中的静态同步方法而无需等待。不管类中的那个静态同步方法被调用,一个类只能由一个线程同时执行。

实例方法中的代码块

有时你不需要同步整个方法,而是同步方法中的一部分。Java可以对方法的一部分进行同步。

在非同步的java方法中的同步块的例子如下所示:

public void add(int value){

    synchronized(this){
       this.count += value;
    }
  }

示例使用java同步块构造器来标记一块代码是同步的。该代码在执行时和同步方法一样。
注意Java同步块构造器用括号将对象括起来。在上例中,使用了“this”,即为调用add方法的实例本身。在同步构造器中用括号括起来的对象叫做监视器对象。上述代码使用监视器对象同步,同步实例方法使用调用方法本身的实例作为监视器对象。

一次只有一个线程能够在同步于同一个监视器对象的Java方法内执行。

下面两个例子都同步他们所调用的实例对象上,因此他们在同步的执行效果上是等效的。

public class MyClass {

   public synchronized void log1(String msg1, String msg2){
      log.writeln(msg1);
      log.writeln(msg2);
   }

   public void log2(String msg1, String msg2){
      synchronized(this){
         log.writeln(msg1);
         log.writeln(msg2);
      }
   }
 }

在上例中,每次只有一个线程能够在两个同步代码块中任意一个方法内执行。

如果第二个同步块不是同步在this实例对象上,那么两个方法发可以被线程同时执行。

静态方法中的代码块

和上面类似,下面是两个静态方法同步的例子。这些方法同步在该方法所属的类对象上。

public class MyClass {
    public static synchronized void log1(String msg1, String msg2){
       log.writeln(msg1);
       log.writeln(msg2);
    }

    public static void log2(String msg1, String msg2){
       synchronized(MyClass.class){
          log.writeln(msg1);
          log.writeln(msg2);
       }
    }
  }

这两个方法不允许同时被线程访问。
如果第二个同步块不是同步在MyClass.class这个对象上。那么这两个方法可以同时被线程访问。

java同步实例

在下面例子中,启动了两个线程,都调用Counter类同一个实例的add方法。因为同步在该方法所属的实例上,所以同时只能有一个线程访问该方法。

public class Counter{
     long count = 0;

     public synchronized void add(long value){
       this.count += value;
     }
  }
  public class CounterThread extends Thread{

     protected Counter counter = null;

     public CounterThread(Counter counter){
        this.counter = counter;
     }

     public void run() {
	for(int i=0; i<10; i++){
           counter.add(i);
        }
     }
  }
  public class Example {

    public static void main(String[] args){
      Counter counter = new Counter();
      Thread  threadA = new CounterThread(counter);
      Thread  threadB = new CounterThread(counter);

      threadA.start();
      threadB.start();
    }
  }

创建了两个线程。他们的构造器引用同一个Counter实例。Counter.add方法是同步在实例上,是因为add方法是实例方法并且被标记上synchronized关键字。因此每次只允许一个线程调用该方法。另外一个线程必须要等到第一个线程退出add()方法时,才能继续执行方法。

如果两个线程引用了两个不同的Counter实例,那么他们可以同时调用add()方法。这些方法调用了不同的对象,因此这些方法也就同步在不同的对象上。这些方法调用将不会被阻塞。如下面这个例子所示:

public class Example {

   public static void main(String[] args){
     Counter counterA = new Counter();
     Counter counterB = new Counter();
     Thread  threadA = new CounterThread(counterA);
     Thread  threadB = new CounterThread(counterB);

     threadA.start();
     threadB.start();
   }
 }

注意这两个线程,threadA和threadB,不再引用同一个counter实例。CounterA和counterB的add方法同步在他们所属的对象上。调用counterA的add方法将不会阻塞调用counterB的add方法。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

同步代码块synchronized的使用与解析 的相关文章

  • Java HashMap 嵌套泛型与通配符

    我正在尝试创建包含自定义类的不同子类的哈希集的哈希映射值的哈希映射 如下所示 HashMap
  • 按位运算符简单地翻转整数中的所有位?

    我必须翻转整数的二进制表示形式中的所有位 鉴于 10101 输出应该是 01010 当与整数一起使用时 完成此操作的按位运算符是什么 例如 如果我正在编写类似的方法int flipBits int n 什么会进入身体 我只需要翻转数字中已经
  • 探索java图像处理的好资源[关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我是图像处理领域的新手 请推荐一些好的资源 书籍和网络链接 来学习 Java 中的图像处理 最适合隐写术分析 适合初学者和高级水平 我看过
  • Java:无安全管理器:RMI 类加载器已禁用

    您好 我有 RMI 应用程序 现在我尝试从客户端调用服务器上的一些方法 我有以下代码 public static void main final String args try Setting the security manager Sy
  • 如何停止使用扫描仪从标准输入读取多行?

    我正在做一个 JAVA 作业 应该处理多行输入 指令显示 输入是从标准输入读取的 给出了示例输入的示例 one 1 two 2 three 3 我不明白上面的示例输入 从标准输入读取 是什么意思 这是我编写的一个测试程序 它可以消除我的困惑
  • Ant 中回显目标描述

  • AWS SDK 2 承担角色

    Bean public DynamoDbClient amazonDynamoDB final AssumeRoleRequest assumeRoleRequest AssumeRoleRequest builder roleSessio
  • 如何构建和使用 TimeSeriesCollections

    我想在图表的 X 轴上显示一些日期 并且here https stackoverflow com questions 5118684 jfreechart histogram with dates据说我必须使用 TimeSeriesColl
  • JPA 的 Hibernate 查询提示

    我一直在尝试为所有可以通过设置的提示找到一个明确的资源Query setHint String Object JPA 中的方法调用 但我一无所获 有人知道一个好的参考吗 See 3 4 1 7 查询提示 http docs jboss or
  • 在Java中将日期“2020-05-22T12:51:20.765111Z”解析为Instant [重复]

    这个问题在这里已经有答案了 如何解析 2020 05 22T12 51 20 732111Z Java 中的 Instant I used LocalDateTime parse startTime DateTimeFormatter of
  • 单元测试、集成测试还是设计中的问题?

    我编写了我的第一个单元测试 我认为它过于依赖其他模块 我不确定是否是因为 这是一个复杂的测试 我实际上已经编写了集成测试或 我的设计有问题 我首先要说的是 虽然我有大约 4 年的开发经验 但我从未学过 也没有人教过自动化测试 我刚刚使用 H
  • 如何从 Trie 中检索给定长度的随机单词

    我有一个简单的 Trie 用来存储大约 80k 长度为 2 15 的单词 它非常适合检查字符串是否是单词 但是 现在我需要一种获取给定长度的随机单词的方法 换句话说 我需要 getRandomWord 5 来返回 5 个字母的单词 所有 5
  • Java:java.util.Preferences 失败

    我的程序将加密的产品密钥数据保存到计算机上java util Preferences类 系统首选项 而不是用户 问题是 在 Windows 和 Linux 上 尚未在 OSX 上测试过 但可能是相同的 如果我不运行该程序sudo或者具有管理
  • Java 常量枚举[重复]

    这个问题在这里已经有答案了 可能的重复 理解 Java 中的枚举 https stackoverflow com questions 1419835 understanding enums in java 为什么我们应该使用枚举而不是 Ja
  • java中的第三个布尔状态是什么?

    虽然我知道根据定义 布尔值仅包含两种状态 真或假 我想知道布尔值在用这些状态之一初始化之前有什么值 它默认为 false http java sun com docs books tutorial java nutsandbolts dat
  • 线程上下文类加载器和普通类加载器的区别

    线程的上下文类加载器和普通类加载器有什么区别 也就是说 如果Thread currentThread getContextClassLoader and getClass getClassLoader 返回不同的类加载器对象 将使用哪一个
  • 动态创建 JSON 对象

    我正在尝试使用以下格式创建 JSON 对象 tableID 1 price 53 payment cash quantity 3 products ID 1 quantity 1 ID 3 quantity 2 我知道如何使用 JSONOb
  • 在java中创建一个XML树并将其转换为json对象

    我尝试创建也能够转换为 json 的树 但对于只有一个xpath 当我尝试实现多个 xpath 时 我无法获得所需的输出 这里我分享一下我的实现 private static Document addElemtbypath List
  • while循环只执行一次

    我很难弄清楚为什么 while 循环实际上不会循环 它运行一次并停止 import java util public class mileskm public static void main String args Scanner inp
  • Swing:创建可拖动组件...?

    我在网上搜索了可拖动 Swing 组件的示例 但我发现示例不完整或不起作用 我需要的是一个摇摆组件那可以是dragged通过鼠标 在另一个组件内 被拖拽的时候 应该已经 改变它的位置 而不仅仅是 跳 到目的地 我很欣赏无需非标准 API 即

随机推荐

  • ORACLE(student)表习题与答案

    1 查询Student表中的所有记录的Sname Ssex和Class列 SELECT sname ssex class FROM student 2 查询教师所有的单位即不重复的Depart列 SELECT distinct depart
  • 集中式日志存储架构

    Hello大家好 欢迎回来 我们今天的视频课程要讨论的内容是 AWS的集中式日志存储架构 包括集中式日志存储架构需要考虑的事项 以及使用了两个AWS账户对架构的实现做了个快速的演示 我们开始今天的内容 集中式日志存储架构 当前 在绝大多数组
  • 对话力码科技:保险科技应用有待深入,价值落地更重要

    保险行业的数字化时机已来 更加专业化的企业才能立于不败之地 数科星球原创 作者丨苑晶 编辑丨大兔 对于国内的大多数企业来说 2023年是个极为重要的年份 在软件行业 随着人工智能等新技术的日益成熟和普及 软件行业迎来黄金时代 在这种趋势下
  • 多点双向重发布

    实验题目 要求 1 两个协议间进行多点双向重发布 2 R7的环回没有宣告在OSPF协议中 而且是后期重发布进去 3 解决环路 所有路径选择最优 且存在备份 实验拓扑图 IP地址与ospf和rip的配置 R1 int g0 0 0 ip ad
  • 华为OD机试真题-计算网络信号 【2023.Q1】

    题目内容 网络信号经过传递会逐层衰减 且遇到阻隔物无法直接穿透 在此情况下需要计算某个位置的网络信号值 注意 网络信号可以绕过阻隔物 array m n 的二维数组代表网格地图 array i j 0代表i行j列是空旷位置 array i
  • 开源协议比较:BSD、Apache、GLP、LGLP、MIT

    BSD开源协议 original BSD license FreeBSD license Original BSD license BSD开源协议是一个给于使用者很大自由的协议 基本上使用者可以 为所欲为 可以自由的使用 修改源代码 也可以
  • Python报错UnicodeDecodeError: ‘gbk‘ codec can‘t decode byte的最新解决办法2022-09-30

    合并txt文件内容时候 Python报错UnicodeDecodeError gbk codec can t decode byte 这个错误是做NLP的小伙伴常见的一个错误 报错原因是读取的文件中有中文 网上找到的解决办法 将 with
  • ProtocolBuffers-3.0.0 For Objective C 的快速集成指南

    一 前言 最近调研 Google的Protocol Buffer 在网上看了几篇相关博客 发现他们讲的都比较复杂 所以就想写一篇简单点的文章 配置环境 mac OS 10 11 5 Xcode7 3 二 Protocol Buffer简介
  • 汉诺塔(Tower of Hanoi)--------递归思路

    汉诺塔问题简介 有三根相邻的柱子 标号为A B C A柱子上从下到上按金字塔状叠放着n个不同大小的圆盘 要把所有盘子一个一个移到柱子C上 并且每次移动 同一根柱子上都只能是大盘子在下 小盘子在上 请问至少需要多少次移动 汉诺塔问题分析 1
  • 剑指 Offer 57. 和为s的两个数字--双指针问题

    这道题有点像之前一道用hashmap做的乱序数组求两数之和等于指定数的问题 两数相加 时间复杂度小于 O n2 而今天这道题 用hashmap也可以做出 但是空间复杂度实在太大 又因为它是排序好的数组 所以二分法或者双指针法比较简单 双指针
  • DRF视图组件

    目录 视图 APIView APIView与View的不同之处 GenericAPIView 通用视图类 类属性 类方法 基于APIView写五个接口 基于GenericAPIVIew写5个接口 五个视图扩展类 ListModelMixin
  • c/c++位字段

    位字段 定义 位字段是C语言中一种存储结构 不同于一般结构体的是它在定义成员的时候需要指定成员所占的位数 所有基础的数据类型 最大的也不过 10 个字节 我们可以自定义的数据类型 struct 通过把若干类型组合在一起 让一种类型可以大很多
  • linux自动安装trojan客户端的shell脚本

    bin bash 安装Trojan客户端 echo 开始安装Trojan客户端 curl O https github com trojan gfw trojan releases download v1 17 0 trojan 1 17
  • Headless Browser Testing With Xvfb

    Jan 09 15 javascripttesting These days when the phrase headless browser is mentioned you immediately think of PhantomJS
  • 【Python基础】用Cython优化Python代码性能

    Cython是一个编程语言 它结合了Python的简洁性和C语言的性能 本文将深入探讨Cython的基本原理 如何将其应用于Python项目 以及如何使用Cython优化Python代码的性能 文章目录 1 Cython简介 2 Cytho
  • getopt使用样本/模板

    this is the sample of use of getopt funtion include
  • python可以进行软件开发吗,python可以做软件开发吗

    本篇文章给大家谈谈python可以进行软件开发吗 以及python可以做软件开发吗 希望对各位有所帮助 不要忘了收藏本站喔 1 python可以开发什么软件 主要可以做小程序 爬虫程序 用于系统编程等等还是很广泛的 Python的应用领域分
  • element-ui中el-table的错位问题解决,以及新的错位问题的出现(与el-tabs相关)

    element ui的表格错位问题 只出现在带有设置了fixed的列的el table中 这是一个渲染机制的问题 通过调用一遍doLayout方法就可以解决 但是套在el tabs里的el table 就是另一种情况了 简单错位 这是我瞎起
  • vr设备的服务器性能指标,让我们一起聊聊VR眼镜技术参数

    时下最炙手可热的数码产品无疑就是VR眼镜了 而作为影响VR体验的重要一部分 VR眼镜技术参数也成为了很多人讨论的焦点 目前市面上的VR设备良莠不齐 具体什么样的VR眼镜技术参数规格才是优秀的产品 而这些VR眼镜技术参数对用户们的体验来说 又
  • 同步代码块synchronized的使用与解析

    Java 同步块 synchronized block 用来标记方法或者代码块是同步的 Java同步块用来避免竞争 本文介绍以下内容 Java同步关键字 synchronzied 实例方法同步 静态方法同步 实例方法中同步块 静态方法中同步