深入理解Java中synchronized三种使用方式:助您写出线程安全的代码

简介: `synchronized` 是 Java 中的关键字,用于实现线程同步,确保多个线程互斥访问共享资源。它通过内置的监视器锁机制,防止多个线程同时执行被 `synchronized` 修饰的方法或代码块。`synchronized` 可以修饰非静态方法、静态方法和代码块,分别锁定实例对象、类对象或指定的对象。其底层原理基于 JVM 的指令和对象的监视器,JDK 1.6 后引入了偏向锁、轻量级锁等优化措施,提高了性能。

添加图片注释,不超过 140 字(可选)


一、概念

synchronized 是一种内置的 Java 关键字,它用于实现线程的同步。当一个线程进入synchronized块或方法时,它获得了锁,这会阻止其他线程同时进入相同的synchronized块或方法,从而确保了共享资源的互斥访问。

synchronized 是 Java 中用于实现线程同步的关键字。它提供了一种独占锁的机制,用于确保多个线程之间的互斥访问共享资源。以下是关于synchronized的更详细解释:

使用方法:

synchronized关键字在Java中有三种主要的使用方式:


添加图片注释,不超过 140 字(可选)

1.修饰非静态方法(锁class的同一实例的此方法)

当您在实例的非静态方法上使用synchronized关键字时,它会将该方法变成同步方法,相当于对当前实例对象(this)加锁,this作为对象监视器。这意味着只有一个线程可以同时执行该实例方法,以确保对该实例的互斥访问。 当前类会创建多个实例对象,synchronized独立的控制每个实例对象的同步。

public synchronized void synchronizedInstanceMethod() {     // 同步的代码块 }

2. 修饰静态方法(锁class的所有实例的此方法)

在静态方法上使用synchronized关键字时,它会将该方法变为同步静态方法,相当于对当前类的Class对象加锁,当前类的Class对象作为对象监视器。这意味着只有一个线程可以同时执行该静态方法,以确保对该类的互斥访问。 当前类会创建多个实例对象,所以实例对应同一个静态方法,所以synchronized控制所以实例对象的同步。锁定的是类的 Class 对象,因此它会阻止不同实例以及静态方法之间的并发执行,因为它们共享相同的 Class 对象。

public static synchronized void synchronizedStaticMethod() {     // 同步的代码块 }

3.修饰代码块(锁定特定的对象)

可以使用synchronized关键字来创建同步代码块,这样可以指定要加锁的对象,括号中括起来的对象就是对象监视器。这允许更细粒度的控制,可以选择对某个特定对象进行同步,而不是整个方法或类。

方式一:

当你使用 synchronized(class) 时,你锁定的是整个类的对象,而不是实例对象。这意味着无论多少实例对象存在,它们都会竞争同一个锁。

Object lock = new Object(); synchronized (lock) {     // 同步的代码块 }

方式二:

当你使用 synchronized(this) 时,你锁定的是当前实例对象(this)。这意味着同一实例的不同方法调用会相互排斥,但不同实例之间的方法调用不会相互排斥。

synchronized (this) {     // 同步的代码块 }


二、实现原理

1、实现原理

synchronized底层原理是基于JVM的指令和对象的监视器(monitor)来实现的。synchronized可以修饰方法或者代码块,用来保证线程的同步和安全。

当一个线程要执行一个被synchronized修饰的方法或代码块时,它需要先获取该方法或代码块所属对象的监视器。如果获取成功,那么该线程就可以执行同步代码,并且监视器的计数器加一。如果获取失败,那么该线程就会阻塞,直到监视器被释放。

当一个线程执行完同步代码后,它会释放监视器,并且监视器的计数器减一。如果计数器为零,那么说明没有线程持有该监视器,其他线程就可以竞争获取该监视器。

synchronized修饰方法时,在字节码层面会有一个ACC_SYNCHRONIZED标志,用来表示该方法是同步的。synchronized修饰代码块时,在字节码层面会有monitorenter和monitorexit两个指令,分别用来进入和退出监视器。

synchronized 的底层实现原理可以概括为以下几点:

  • synchronized 通过监视器锁来实现线程同步。
  • 每个 Java 对象都有一个监视器锁。
  • 线程在获取了对象的监视器锁后,可以执行被修饰的代码。
  • 线程在释放了对象的监视器锁后,其他线程可以尝试获取监视器锁。

2、JDK底层的优化

synchronized在JDK1.6之后进行了优化,引入了偏向锁,轻量级锁,自旋锁等概念,用来提高性能和减少阻塞开销。以下是一些常见的优化详细说明:

  1. 偏向锁:JDK引入了偏向锁,它会将锁定的对象与线程相关联,当一个线程获得锁时,它会标记对象为已偏向该线程,以后再次进入同步块时,不需要竞争锁,而是直接获得。这对于减少无竞争情况下的锁开销非常有用。
  2. 轻量级锁:在低竞争情况下,JDK使用轻量级锁来减小锁开销。轻量级锁采用自旋方式来等待锁的释放,而不是进入阻塞状态。
  3. 自旋锁:当轻量级锁尝试获取锁失败时,JDK可以选择使用自旋锁。自旋锁不会使线程进入阻塞状态,而是一直尝试获取锁,通常在短时间内完成。这对于低竞争锁非常有用。
  4. 适应性自旋:JDK中的锁可以根据历史性能数据来调整自旋等待的次数,以达到更好的性能。

这些优化措施有助于提高synchronized的性能,使其在不同的竞争场景中更加高效。但请注意,优化是基于JVM和硬件平台的,因此在不同的环境中表现可能会有所不同。

三、相关题目

问题1:synchronized 是什么?它的作用是什么?

答案:synchronized 是Java中的关键字,用于实现多线程同步。它的主要作用是确保在同一时刻只有一个线程可以访问被synchronized修饰的代码块或方法,以避免多线程之间的竞态条件和数据不一致问题。

问题2:synchronized 有哪些用法?

答案:synchronized 可以用于以下用法:

  • 同步非静态实例方法:synchronized 修饰非静态方法,锁定的是实例对象。
  • 同步静态方法:synchronized 修饰静态方法,锁定的是类对象。
  • 同步代码块:synchronized 修饰代码块,可以手动指定锁对象,灵活控制同步范围。

问题3:什么是锁对象?

答案:锁对象是在synchronized代码块或方法中用于实现同步的对象。对于同步实例方法,锁对象是实例对象本身(this),而对于同步静态方法,锁对象是类的Class对象。对于同步代码块,你可以手动指定锁对象。

问题4:什么是重入锁?

答案:重入锁是指当一个线程持有锁时,它可以多次进入被锁定的代码块或方法而不会被阻塞。Java中的synchronized是可重入锁的一个例子,这意味着同一线程可以多次获取同一个锁,而不会造成死锁。

问题5:什么是偏向锁?

答案:偏向锁是一种优化,用于减少锁竞争的开销。它允许线程在没有竞争的情况下快速获得锁,而不必像重量级锁那样进入阻塞状态。只有在多线程竞争锁时,偏向锁才会升级为重量级锁。

问题6:什么是自旋锁?

答案:自旋锁是一种轻量级锁,它在尝试获取锁时不会立即阻塞线程,而是会在循环中不断尝试获取锁。这可以减少线程阻塞和恢复的开销,但如果锁竞争激烈,自旋锁可能会浪费大量CPU时间。

问题7:什么是锁粗化?

答案:锁粗化是一种优化,它将多个连续的synchronized块合并成一个更大的同步块,减少了锁操作的开销。这可以避免频繁地获取和释放锁,提高性能。

问题8:什么是锁消除?

答案:锁消除是一种优化,它通过静态分析来检测某些锁是不必要的,然后将其删除,以提高程序的性能。这通常发生在编译器级别。

问题9:synchronized 与 volatile 有什么区别?

答案:synchronized 用于实现多线程同步,确保线程之间的可见性和原子性。volatile 用于确保变量的可见性,但不能实现原子性。synchronized 具有更广泛的用途,而 volatile 主要用于标记变量以确保可见性。


目录
相关文章
|
5天前
|
JavaScript NoSQL Java
接替此文【下篇-服务端+后台管理】优雅草蜻蜓z系统JAVA版暗影版为例-【蜻蜓z系列通用】-2025年全新项目整合搭建方式-这是独立吃透代码以后首次改变-独立PC版本vue版搭建教程-优雅草卓伊凡
接替此文【下篇-服务端+后台管理】优雅草蜻蜓z系统JAVA版暗影版为例-【蜻蜓z系列通用】-2025年全新项目整合搭建方式-这是独立吃透代码以后首次改变-独立PC版本vue版搭建教程-优雅草卓伊凡
142 96
接替此文【下篇-服务端+后台管理】优雅草蜻蜓z系统JAVA版暗影版为例-【蜻蜓z系列通用】-2025年全新项目整合搭建方式-这是独立吃透代码以后首次改变-独立PC版本vue版搭建教程-优雅草卓伊凡
|
1天前
|
Java 程序员 开发者
Java社招面试题:一个线程运行时发生异常会怎样?
大家好,我是小米。今天分享一个经典的 Java 面试题:线程运行时发生异常,程序会怎样处理?此问题考察 Java 线程和异常处理机制的理解。线程发生异常,默认会导致线程终止,但可以通过 try-catch 捕获并处理,避免影响其他线程。未捕获的异常可通过 Thread.UncaughtExceptionHandler 处理。线程池中的异常会被自动处理,不影响任务执行。希望这篇文章能帮助你深入理解 Java 线程异常处理机制,为面试做好准备。如果你觉得有帮助,欢迎收藏、转发!
32 14
|
4天前
|
安全 Java 程序员
Java 面试必问!线程构造方法和静态块的执行线程到底是谁?
大家好,我是小米。今天聊聊Java多线程面试题:线程类的构造方法和静态块是由哪个线程调用的?构造方法由创建线程实例的主线程调用,静态块在类加载时由主线程调用。理解这些细节有助于掌握Java多线程机制。下期再见! 简介: 本文通过一个常见的Java多线程面试题,详细讲解了线程类的构造方法和静态块是由哪个线程调用的。构造方法由创建线程实例的主线程调用,静态块在类加载时由主线程调用。理解这些细节对掌握Java多线程编程至关重要。
34 13
|
5天前
|
安全 Java 开发者
【JAVA】封装多线程原理
Java 中的多线程封装旨在简化使用、提高安全性和增强可维护性。通过抽象和隐藏底层细节,提供简洁接口。常见封装方式包括基于 Runnable 和 Callable 接口的任务封装,以及线程池的封装。Runnable 适用于无返回值任务,Callable 支持有返回值任务。线程池(如 ExecutorService)则用于管理和复用线程,减少性能开销。示例代码展示了如何实现这些封装,使多线程编程更加高效和安全。
|
1月前
|
SQL Java 数据库连接
如何在 Java 代码中使用 JSqlParser 解析复杂的 SQL 语句?
大家好,我是 V 哥。JSqlParser 是一个用于解析 SQL 语句的 Java 库,可将 SQL 解析为 Java 对象树,支持多种 SQL 类型(如 `SELECT`、`INSERT` 等)。它适用于 SQL 分析、修改、生成和验证等场景。通过 Maven 或 Gradle 安装后,可以方便地在 Java 代码中使用。
233 11
|
1月前
|
监控 Java
java异步判断线程池所有任务是否执行完
通过上述步骤,您可以在Java中实现异步判断线程池所有任务是否执行完毕。这种方法使用了 `CompletionService`来监控任务的完成情况,并通过一个独立线程异步检查所有任务的执行状态。这种设计不仅简洁高效,还能确保在大量任务处理时程序的稳定性和可维护性。希望本文能为您的开发工作提供实用的指导和帮助。
107 17
|
2月前
|
Java
Java—多线程实现生产消费者
本文介绍了多线程实现生产消费者模式的三个版本。Version1包含四个类:`Producer`(生产者)、`Consumer`(消费者)、`Resource`(公共资源)和`TestMain`(测试类)。通过`synchronized`和`wait/notify`机制控制线程同步,但存在多个生产者或消费者时可能出现多次生产和消费的问题。 Version2将`if`改为`while`,解决了多次生产和消费的问题,但仍可能因`notify()`随机唤醒线程而导致死锁。因此,引入了`notifyAll()`来唤醒所有等待线程,但这会带来性能问题。
Java—多线程实现生产消费者
|
1月前
|
JSON Java 数据挖掘
利用 Java 代码获取淘宝关键字 API 接口
在数字化商业时代,精准把握市场动态与消费者需求是企业成功的关键。淘宝作为中国最大的电商平台之一,其海量数据中蕴含丰富的商业洞察。本文介绍如何通过Java代码高效、合规地获取淘宝关键字API接口数据,帮助商家优化产品布局、制定营销策略。主要内容包括: 1. **淘宝关键字API的价值**:洞察用户需求、优化产品标题与详情、制定营销策略。 2. **获取API接口的步骤**:注册账号、申请权限、搭建Java开发环境、编写调用代码、解析响应数据。 3. **注意事项**:遵守法律法规与平台规则,处理API调用限制。 通过这些步骤,商家可以在激烈的市场竞争中脱颖而出。
|
1月前
|
缓存 安全 算法
Java 多线程 面试题
Java 多线程 相关基础面试题
|
3天前
|
Python
python3多线程中使用线程睡眠
本文详细介绍了Python3多线程编程中使用线程睡眠的基本方法和应用场景。通过 `time.sleep()`函数,可以使线程暂停执行一段指定的时间,从而控制线程的执行节奏。通过实际示例演示了如何在多线程中使用线程睡眠来实现计数器和下载器功能。希望本文能帮助您更好地理解和应用Python多线程编程,提高程序的并发能力和执行效率。
32 20

热门文章

最新文章