Java并发编程系列之十:synchronized(1)

2024-05-30 16:48

本文主要是介绍Java并发编程系列之十:synchronized(1),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

在多线程并发访问资源(这类资源称为临街资源)的时候,由于割裂来了原子操作,所以会导致数据不一致的情况。为了避免这种情况,需要使用同步机制,同步机制能够保证多线程并发访问数据的时候不会出现数据不一致的情况。

一种同步机制是使用synchronized关键字,这种机制也称为互斥锁机制,这就意味着同一时刻只能有一个线程能够获取到锁,获得的锁也被称为互斥锁。其他需要获取该互斥锁的线程只能被阻塞,直到获取到该锁的线程释放锁。在Java中,每个类都有一个内置锁,之所以如此,是因为Java并发专家认为这样可以避免显式创建锁。

通过下面的代码可以直到synchronized到底是如何实现的:

package com.rhwayfun.concurrency;/*** Created by rhwayfun on 16-4-3.*/
public class Synchronied {public static void main(String[] args){synchronized (Synchronied.class){}a();}public static synchronized void a() {}
}

使用java -v Synchronized.class命令可以看到如下的结果:

  public static void main(java.lang.String[]);descriptor: ([Ljava/lang/String;)Vflags: ACC_PUBLIC, ACC_STATICCode:stack=2, locals=3, args_size=10: ldc           #2                  // class com/rhwayfun/concurrency/Synchronied2: dup3: astore_14: monitorenter5: aload_16: monitorexit7: goto          1510: astore_211: aload_112: monitorexit13: aload_214: athrow15: invokestatic  #3                  // Method a:()V18: returnException table:from    to  target type5     7    10   any10    13    10   anyLineNumberTable:line 8: 0line 10: 5line 11: 15line 12: 18LocalVariableTable:Start  Length  Slot  Name   Signature0      19     0  args   [Ljava/lang/String;public static synchronized void a();descriptor: ()Vflags: ACC_PUBLIC, ACC_STATIC, ACC_SYNCHRONIZEDCode:stack=0, locals=0, args_size=00: returnLineNumberTable:line 15: 0
}
SourceFile: "Synchronied.java"

通过编译的class文件可以看到synchronized代码块使用了monitorenter和monitorexit两个指令分别获取锁标记和释放锁标记,而synchronized方法使用了ACC_SYNCHRONIZED来完成锁的获取与释放的。也就是锁的获取与释放synchronized关键字自动帮我们完成了。

对于使用synchronized关键字实现的同步机制由如下几点补充说明:

  1. 如果同一个方法有多个线程访问,那么每个线程都有自己的线程拷贝(拷贝存储在工作内存中)
  2. 类的实例都有自己的对象锁,如果一个线程成功获取到该实例的对象锁那么当其他线程需要获取该实例的对象锁时,便需要阻塞等待,直到该实例的对象锁被成功释放。对象锁可以作用在同步方法或者同步代码块中
  3. 如果不同的线程访问的是不同实例的对象锁,那么不会互相阻塞,因为不同实例的对象锁是不同的
  4. 获得实例的对象锁的线程会让其他想要获取相同对象锁的线程阻塞在synchronized代码外,比如由两个synchronized方法a()、b(),那么如果线程A成功进入了同步方法a(),那么该线程便获取了该实例(比如实例obj)的对象锁,而如果其他线程想要执行另一个同步方法b(),就会阻塞在外面,因为a()和b()持有的都是对象obj的对象锁
  5. 持有一个实例的对象锁不会阻止该线程被置换出来,也不会阻塞其他线程执行非synchronized方法,因为非synchronized方法执行的时候不需要获取实例的对象锁
  6. 使用同步代码块的时候,括号的对象可以为任意Object实例,当为this时,指的是当前对象的对象锁
  7. 类锁主要用于控制对static成员变量的并发访问
  8. synchronized块(可以是同步方法或者同步代码块)是可重入的,每次重入会把锁的计数器加1,每次退出将计数器减1,当计数器的值为0的时候,锁便被释放了
  9. Java SE 1.6 为了减少获得锁和释放锁的性能消耗引入了偏向锁和轻量级锁,所以使用synchronized也没有那么重量级了

这篇关于Java并发编程系列之十:synchronized(1)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1016554

相关文章

Spring boot整合dubbo+zookeeper的详细过程

《Springboot整合dubbo+zookeeper的详细过程》本文讲解SpringBoot整合Dubbo与Zookeeper实现API、Provider、Consumer模式,包含依赖配置、... 目录Spring boot整合dubbo+zookeeper1.创建父工程2.父工程引入依赖3.创建ap

SpringBoot结合Docker进行容器化处理指南

《SpringBoot结合Docker进行容器化处理指南》在当今快速发展的软件工程领域,SpringBoot和Docker已经成为现代Java开发者的必备工具,本文将深入讲解如何将一个SpringBo... 目录前言一、为什么选择 Spring Bootjavascript + docker1. 快速部署与

Spring Boot spring-boot-maven-plugin 参数配置详解(最新推荐)

《SpringBootspring-boot-maven-plugin参数配置详解(最新推荐)》文章介绍了SpringBootMaven插件的5个核心目标(repackage、run、start... 目录一 spring-boot-maven-plugin 插件的5个Goals二 应用场景1 重新打包应用

SpringBoot+EasyExcel实现自定义复杂样式导入导出

《SpringBoot+EasyExcel实现自定义复杂样式导入导出》这篇文章主要为大家详细介绍了SpringBoot如何结果EasyExcel实现自定义复杂样式导入导出功能,文中的示例代码讲解详细,... 目录安装处理自定义导出复杂场景1、列不固定,动态列2、动态下拉3、自定义锁定行/列,添加密码4、合并

Spring Boot集成Druid实现数据源管理与监控的详细步骤

《SpringBoot集成Druid实现数据源管理与监控的详细步骤》本文介绍如何在SpringBoot项目中集成Druid数据库连接池,包括环境搭建、Maven依赖配置、SpringBoot配置文件... 目录1. 引言1.1 环境准备1.2 Druid介绍2. 配置Druid连接池3. 查看Druid监控

Java中读取YAML文件配置信息常见问题及解决方法

《Java中读取YAML文件配置信息常见问题及解决方法》:本文主要介绍Java中读取YAML文件配置信息常见问题及解决方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要... 目录1 使用Spring Boot的@ConfigurationProperties2. 使用@Valu

创建Java keystore文件的完整指南及详细步骤

《创建Javakeystore文件的完整指南及详细步骤》本文详解Java中keystore的创建与配置,涵盖私钥管理、自签名与CA证书生成、SSL/TLS应用,强调安全存储及验证机制,确保通信加密和... 目录1. 秘密键(私钥)的理解与管理私钥的定义与重要性私钥的管理策略私钥的生成与存储2. 证书的创建与

浅析Spring如何控制Bean的加载顺序

《浅析Spring如何控制Bean的加载顺序》在大多数情况下,我们不需要手动控制Bean的加载顺序,因为Spring的IoC容器足够智能,但在某些特殊场景下,这种隐式的依赖关系可能不存在,下面我们就来... 目录核心原则:依赖驱动加载手动控制 Bean 加载顺序的方法方法 1:使用@DependsOn(最直

SpringBoot中如何使用Assert进行断言校验

《SpringBoot中如何使用Assert进行断言校验》Java提供了内置的assert机制,而Spring框架也提供了更强大的Assert工具类来帮助开发者进行参数校验和状态检查,下... 目录前言一、Java 原生assert简介1.1 使用方式1.2 示例代码1.3 优缺点分析二、Spring Fr

java使用protobuf-maven-plugin的插件编译proto文件详解

《java使用protobuf-maven-plugin的插件编译proto文件详解》:本文主要介绍java使用protobuf-maven-plugin的插件编译proto文件,具有很好的参考价... 目录protobuf文件作为数据传输和存储的协议主要介绍在Java使用maven编译proto文件的插件