总结篇(27)---Java并发及锁(1)Synchronized

本文详细介绍了Java中的synchronized关键字,解释了其如何实现线程间的同步操作,并探讨了它在实例对象与类对象上的不同作用范围。同时,文章还介绍了synchronized在字节码层面的具体实现方式。

Synchronized

  • 在java中synchronized关键词具有使每个线程依次排队操作共享变量的功能。

一、Synchronized使用


  • 当锁住的是实例对象,它是作用于该实例的范围,其它不同的实例对象仍然可以执行。
  • 当锁住的是类对象,他是作用于某个类的范围,只要是该类的实例对象都会受到影响。

二、Synchronized原理


当使用了synchronized,会在生成的class信息中出现下面两种情况:
(1)同步代码块使用了monitorenter和monitorexit指令实现。
代码:

class信息中:


(2)同步方法中依靠方法修饰符上ACC_SYNCHRONIZED实现。
代码:

class信息中:

备注:

1)Synchronized的自旋是怎么实现的?代码如何实现

        在Java中,synchronized关键字的底层实现确实涉及自旋优化,但这一过程是由JVM自动管理的,开发者无需手动编写自旋代码。以下是其实现原理及代码示例:

synchronized自旋的实现原理:

1-1)锁升级机制

  • 偏向锁:首次访问时标记线程ID,无竞争时直接进入。
  • 轻量级锁(自旋锁):当发生轻微竞争时,线程通过CAS自旋尝试获取锁。
  • 重量级锁:自旋失败后,锁升级为操作系统级别的互斥锁,线程进入阻塞状态。

1-2)自旋的实现

  • 轻量级锁阶段,JVM会让未获取锁的线程执行忙循环(自旋),通过CAS(Compare-And-Swap)操作不断检查锁状态。
  • CAS通过硬件指令(如x86的cmpxchg)保证原子性,确保只有一个线程能成功修改锁标志。

1-3)自适应自旋优化

  • JVM会根据锁的历史状态动态调整自旋次数(如之前自旋成功则允许更长时间的自旋)。

2)Wait/notify/notifyAll方法需不需要被包含在synchronized块中?这是为什么

        在Java中,wait()notify()notifyAll()方法必须被包含在synchronized块或同步方法中,否则会抛出IllegalMonitorStateException异常。

2-1)锁的持有是前提条件

  • wait()notify()的语义要求线程必须 先持有对象的监视器锁(Monitor Lock)才能调用这些方法。 
  • 直接原因:若未持有锁,调用这些方法会触发IllegalMonitorStateException
  • 底层逻辑:这些方法依赖锁机制实现线程间协作,锁的存在保证了线程对共享资源的安全访问。

2-2)保证操作的原子性

  • wait()方法会释放当前锁并让线程进入等待状态,而notify()会唤醒其他等待线程。
  • 这两个操作必须在一个原子步骤中完成,否则可能导致:
    • 竞态条件(Race Condition):例如,线程A调用notify()后,线程B尚未进入等待状态,导致通知丢失。
    • 数据不一致:共享资源的状态可能在未同步的情况下被意外修改。

2-3)内存可见性

  • synchronized块不仅提供互斥,还确保内存可见性(通过happens-before规则)。
  • 若不在同步块中调用wait()notify(),线程可能无法感知其他线程对共享变量的修改(如缓存不一致问题)。

更多java基础总结(适合于java基础学习、java面试常规题):

总结篇(1)---复用类

总结篇(2)---多态

总结篇(3)---内部类 (1)内部类的基本概念

总结篇(4)---内部类 (2)内部类之静态内部类

总结篇(5)---内部类 (3)内部类之成员内部类

总结篇(6)---内部类 (4)内部类之局部内部类

总结篇(7)---内部类 (5)内部类之匿名内部类

总结篇(8)---序列化

总结篇(9)---字符串及基本类 (1)字符串及基本类之基本数据类型

总结篇(10)---字符串及基本类 (2)字符串及基本类之java中公共方法及操作

总结篇(11)---字符串及基本类 (3)String对象

总结篇(12)---字符串及基本类 (4)Integer对象

总结篇(13)--- Java注解及元注解

总结篇(14)---JVM(java虚拟机) (1)JVM虚拟机概括

总结篇(15)---JVM(java虚拟机) (2)类加载器

总结篇(16)---JVM(java虚拟机) (3)运行时数据区

总结篇(17)---JVM(java虚拟机) (4)垃圾回收

总结篇(18)---JVM(java虚拟机) (5)垃圾回收算法

总结篇(19)---JVM(java虚拟机) (6)JVM调优

总结篇(20)---反射

总结篇(21)---Java IO

总结篇(22)---Java 进程

总结篇(23)---Java线程及其相关(1)线程介绍

总结篇(24)---Java线程及其相关(2)多线程及其问题

总结篇(25)---Java线程及其相关(3)线程池及其问题

总结篇(26)---Java线程及其相关(4)ThreadLocal

总结篇(27)---Java并发及锁(1)Synchronized

总结篇(28)---Java并发及锁(2)Volatile

总结篇(29)---Java并发及锁(3)Lock

总结篇(30)---Java并发及锁(4)常见锁及分类

总结篇(31)---JUC工具类(1)CountDownLatch

总结篇(32)---JUC工具类(2)CyclicBarrier

总结篇(33)---JUC工具类(3)Semaphore

总结篇(34)---JUC工具类(4)Exchanger

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

sun cat

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值