线程锁---synchronized

本文详细介绍了Java中线程锁的使用方法,包括synchronized关键字的应用、死锁现象的产生及避免方式,以及可重入锁ReentrantLock的特性。通过实例说明了如何确保线程安全,特别关注于基本数据类型在多线程环境下的安全性问题。

synchronized

互斥锁

修饰一个方法或一个代码块时,可以保证在同一时刻最多只有一个线程执行该代码
例:当使用基本数据类型 int 并对其进行操作时,会出现线程不安全的情况。
可以使用两种方法解决:
(1)使用AtomicInteger保证原子性
(2)加锁,使用synchronized修饰方法或代码块
在这里插入图片描述
在这里插入图片描述
使用synchronized修饰方法后:
在这里插入图片描述
或者使用synchronized()锁定代码块:
在这里插入图片描述
由于num为基本数据类型,基本数据类型不能锁,所以后面为this,表示锁定当前的对象(ticket)

死锁

使用synchronized()锁住后不能自动释放
可能形成死循环,使程序无法停止
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

可重入锁

ReentrantLock
在这里插入图片描述
可以自动释放锁

Java中的synchronized锁会经历从无锁到偏向锁,再到轻量级锁,最后到重量级锁的升级过程,这种优化称为锁升级或锁膨胀,其目的是在不同的并发压力下优化锁的性能[^1][^2][^4]。以下是具体的原理及过程: ### 无锁 这是没有开启偏向锁时的状态。在JDK 1.6之后,偏向锁默认开启,但存在一个偏向延迟,需在JVM启动之后的一定秒数后才能开启,该时间可通过JVM参数进行设置,同时是否开启偏向锁也能通过JVM参数设置[^4]。 ### 偏向锁 在偏向锁开启后,若还没有线程拿到锁,此状态叫做匿名偏向。当一个线程拿到偏向锁时,下次竞争锁只需将线程ID与Mark Word中存储的线程ID进行比较,若相同则直接获取锁(锁偏向于该线程),无需进行CAS操作和挂起线程的操作。偏向锁存储的内容为线程ID和Epoch(时间戳),适用于同一线程重复访问的场景,加解锁几乎无代价[^1][^4]。 ### 轻量级锁 线程主要通过CAS操作实现轻量级锁。将对象的Mark Word存储到线程的虚拟机栈上,然后通过CAS把对象的Mark Word的内容设置为指向Displaced Mark Word的指针,若设置成功则获取锁。线程出临界区时,也需使用CAS,若替换成功则同步成功,失败则表示有其他线程在获取锁,释放锁后需唤醒被挂起的线程。轻量级锁存储的是指向栈中锁记录的指针,适用于多线程交替访问的场景,但自旋会消耗CPU资源[^1][^4]。当偏向锁被第二个线程访问时,会升级为轻量级锁,第二个线程会通过自旋尝试获取锁。若当前只有一个等待线程,该线程将通过自旋等待,不过当自旋超过一定次数,或者一个线程已持有锁,另一个线程在自旋,此时又有第三个线程来访时,轻量级锁会升级为重量级锁[^1][^5]。 ### 重量级锁 当有两个以上的线程获取锁时,轻量级锁会升级为重量级锁。因为CAS若未成功会始终自旋,进行while循环操作,非常消耗CPU。升级为重量级锁后,线程会被操作系统调度然后挂起,可节约CPU资源。重量级锁存储的是指向互斥量(mutex)的指针,适用于多线程竞争激烈的场景,但线程阻塞唤醒开销大[^1][^4]。 锁升级的完整流程可概括为:第一个线程访问时为无锁状态,之后进入偏向锁状态;出现第二个线程时,可能升级为轻量级锁;若自旋超过阈值或有第三个线程访问,会升级为重量级锁,还存在批量重偏向和批量撤销的情况,以及重置偏向锁的操作[^1]。 ### 代码示例 ```java public class SynchronizedLockUpgradeExample { private static final Object lock = new Object(); public static void main(String[] args) { // 模拟第一个线程获取锁 new Thread(() -> { synchronized (lock) { System.out.println("Thread 1 acquired the lock."); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } }).start(); // 模拟第二个线程获取锁 new Thread(() -> { try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (lock) { System.out.println("Thread 2 acquired the lock."); } }).start(); } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值