【JavaEE初阶】深入理解synchronized关键字及其应用场景

synchronized 起到了互斥效果,当某个线程执行到某个对象的 synchronized 块时,其他线程若也执行到同一个对象的 synchronized 块,则会阻塞等待。

进入 synchronized 修饰的代码块相当于加锁,退出则相当于解锁。

图片[1]-【JavaEE初阶】深入理解synchronized关键字及其应用场景-山海云端论坛

synchronized 使用的锁存在于 Java 对象头中。

图片[2]-【JavaEE初阶】深入理解synchronized关键字及其应用场景-山海云端论坛

可以粗略地理解为,每个对象在内存中都有一块内存表示当前的“锁定”状态,类似于厕所的“有人/无人”。

如果当前是“无人”状态,则可以使用,使用时需要设为“有人”状态。

如果当前是“有人”状态,则其他人无法使用,只能排队。

后面排队的人我们可以称为“阻塞等待”。

阻塞等待是指,针对每一把锁,操作系统内部都维护了一个等待队列。当某个线程持有锁时,其他线程尝试加锁时会被阻塞,直到之前的线程释放锁并操作系统唤醒一个新的线程。

注意,释放锁后,下一个线程并不是立即获取锁,而是依赖操作系统的唤醒调度。

补充:synchronized 的底层是使用操作系统的 mutex lock 实现的。

可重入

synchronized 同步块对同一条线程是可重入的,不会出现自己把自己锁死的问题。

这种问题发生在一个线程没有释放锁,然后又尝试再次加锁的情况下。

Java 中的 synchronized 是可重入锁,因此没有此类问题。

使用方法

直接修饰普通方法

锁是当前实例对象,进入同步代码前需获得当前实例的锁。

<code>public class SynchronizedDemo { public synchronized void method() { // 同步代码块 } }</code>

修饰静态方法

锁是当前类的 class 对象,进入同步代码前需获得当前类对象的锁。

<code>public class SynchronizedDemo { public synchronized static void method() { // 同步代码块 } }</code>

修饰代码块

同步方法块,锁是括号里面的对象,进入同步代码块前需获得给定对象的锁。

<code>public class SynchronizedDemo { public void method() { synchronized (this) { // 同步代码块 } } }</code>

Java 标准库中的线程安全类

Java 标准库中的很多类都是线程不安全的,这些类可能会涉及到多线程修改共享数据,又没有任何加锁措施。

但是还有一些是线程安全的,使用了一些锁机制来控制。

不推荐使用的原因是:当使用这些类时,每一次都会伴随加锁操作,如果该操作不需要加锁,则会造成时间浪费。

注意:String 虽然没有加锁,但不涉及“修改”,仍然是线程安全的。

总结

本文深入探讨了 synchronized 关键字的作用机制及其使用场景,希望对您有所帮助。

© 版权声明
THE END
喜欢就支持一下吧
点赞6 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容