synchronized是什么?底层原理是什么?jdk1.7 和jdk1.8中的synchronized有什么区别?

本文详细介绍了Java中`synchronized`的关键字,包括其底层原理、JDK1.7和1.8的实现差异,以及在不同场景下的使用和替代方案。着重讨论了重量级锁、轻量级锁和偏向锁的优化,以及如何在Java并发编程中选择合适的同步机制。
摘要由CSDN通过智能技术生成

synchronized 介绍

概述

synchronized 是 Java 语言中的一个关键字,用于控制对共享资源的访问。它可以修饰方法、代码块或类,确保同一时刻只有一个线程可以执行被修饰的代码

底层原理

synchronized 的底层原理是使用锁(Lock)来实现互斥访问。每个对象都拥有一个互斥锁,当一个线程获取对象的锁之后,其他线程试图获取该锁时会阻塞,直到该线程释放锁。

JDK 1.7 和 JDK 1.8 中的 synchronized 区别

JDK 1.7 synchronized 的底层实现

在 JDK 1.7 中,synchronized 的底层实现使用的是 “重量级锁”(heavyweight lock)。它是一种基于操作系统互斥锁的实现。

具体实现过程如下:

  1. 当一个线程试图进入一个 synchronized 代码块时,会先尝试获取对象的锁。
  2. 如果锁是可用的,则线程会成功获取锁并进入代码块。
  3. 如果锁已经被其他线程持有,则当前线程会阻塞,直到该线程释放锁。
  4. 线程执行完 synchronized 代码块后,会释放锁。

重量级锁的实现细节:

  • 重量级锁使用的是 “互斥锁”(Mutex) 来实现。互斥锁是一种操作系统提供的同步机制,可以保证同一时刻只有一个线程可以持有锁。
  • 每个对象都拥有一个互斥锁,称为 “监视器锁”(monitor lock)
  • 线程获取锁的操作称为 “加锁”(lock),释放锁的操作称为 “解锁”(unlock)

重量级锁的缺点:

  • 重量级锁的实现比较复杂,会带来一定的性能开销。
  • 重量级锁是全局性的,也就是说,即使只有一个线程需要访问共享资源,也需要获取整个对象的锁,这可能会导致其他线程的阻塞。

JDK 1.8 synchronized 的底层实现:

在 JDK 1.8 中,synchronized 的底层实现依赖于对象的 “对象头”(object header)。对象头是对象内部存储的一部分数据,用于存储对象的运行时信息,包括锁信息、哈希码、GC 信息等。

对象头的结构:

  • Mark Word: 存储对象的锁信息,包括锁标志、偏向锁信息、轻量级锁信息等。
  • Klass Word: 存储对象的类型信息,指向对象的类元数据。
  • 其他信息: 存储对象的哈希码、GC 信息等。

锁标志:

  • 锁标志是一个 32 位的比特位,用于表示对象的锁状态。
  • 锁标志的低 16 位表示对象的锁状态,包括无锁、偏向锁、轻量级锁、重量级锁等。
  • 锁标志的高 16 位表示对象的哈希码。

偏向锁:

  • 偏向锁是一种优化手段,在没有竞争的情况下,直接将锁分配给第一个获取锁的线程。
  • 偏向锁的信息存储在锁标志的低 4 位中。

轻量级锁:

  • 轻量级锁是一种优化手段,使用 CAS 操作来实现互斥访问。
  • 轻量级锁的信息存储在锁标志的低 12 位中。

重量级锁:

  • 重量级锁是一种传统的锁实现,使用操作系统互斥锁来实现。
  • 当锁升级为重量级锁时,会使用对象的监视器锁。

总结:

在 JDK 1.7 中,synchronized 使用的是 “重量级锁”(heavyweight lock),它是一种基于操作系统互斥锁的实现。重量级锁的实现比较复杂,会带来一定的性能开销。

在 JDK 1.8 中,synchronized 引入了 “轻量级锁”(lightweight lock)“偏向锁”(biased lock) 两种优化手段。轻量级锁使用的是 CAS 操作来实现互斥访问,性能比重量级锁更高。偏向锁则是在没有竞争的情况下,直接将锁分配给第一个获取锁的线程,进一步提高性能。

synchronized 的使用:

synchronized 可以修饰方法、代码块或类。

  • 修饰方法: 表示整个方法都加锁
  • 修饰代码块: 表示只对代码块中的代码加锁
  • 修饰类: 表示对类的所有静态方法和静态变量加锁

synchronized 的示例:

Java

public class SynchronizedExample {

    private static int count = 0;

    public static void main(String[] args) {
        // 使用 synchronized 修饰方法
        synchronized void increment() {
            count++;
        }

        // 使用 synchronized 修饰代码块
        synchronized (this) {
            count++;
        }

        // 使用 synchronized 修饰类
        synchronized (SynchronizedExample.class) {
            count++;
        }
    }
}

synchronized 的替代方案:

  • ReentrantLock: 可重入锁,可以避免死锁
  • ReadWriteLock: 读写锁,可以提高读操作的性能
  • StampedLock: 戳锁,可以提高性能和灵活性

总结

synchronized 是 Java 语言中一种重要的同步机制,可以有效地保证共享资源的访问安全。在 JDK 1.8 中,synchronized 进行了优化,性能得到了进一步提升。Java 中提供了其他一些同步机制,例如 ReentrantLockSemaphorejava.util.concurrent 包中的并发类。

  • 29
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值