成员变量与局部变量与sychronized和效率与线程安全的关系

本文探讨了在Java虚拟机(JVM)中线程安全性的实现方式,分析了使用成员变量、局部变量及同步代码块等不同模式的利弊,并提出通过final关键字确保线程安全的方法。

从JVM内存的层面来讲,线程不安全是因为多线程共用堆内存引起的,多线程是为了提高程序运行效率而来的,因为成员变量在堆内存中,而局部变量是随栈的所以不会影响线程安全,另外可以通过sychronized(){}修饰代码或方法达到对共用数据的保护。这样我们就有了三种模式,三种模式各有利弊。


1,使用成员变量

优点节约了栈消耗的内存,总体节约了内存

缺点是多线程下会造成线程不安全

2,使用局部变量

优点是不会造成线程不安全

缺点是浪费了栈内存,总体浪费内存,效率也低下

3,使用同步代码块

优点是不会造成线程的不安全,也不浪费内存

缺点是多线程下会造成效率低下




*如果用成员变量多线程下面也是可以确保安全的,就是成员变量设置为只可读不能写final或者只能写一次

<think>我们正在讨论ReentrantLocksynchronized的区别。根据引用[1]引用[2]的内容,我们可以从多个维度进行比较。 同时,引用[3]提到了ReentrantLock的Condition可以更灵活地控制线程的等待唤醒。 我们将从以下几个方面进行对比: 1. 锁的获取释放机制 2. 可中断性 3. 公平锁非公平锁 4. 条件变量(Condition) 5. 性能 6. 使用方式 注意:引用[1]说明了ReentrantLock支持重入,并且可以分析公平锁非公平锁的行为;引用[2]解释了synchronized的底层原理(基于监视器锁);引用[3]提到了ReentrantLock的Condition可以分组唤醒线程。 下面进行详细说明。 </think>### ReentrantLock synchronized 的核心区别 #### 一、锁实现机制对比 | **特性** | **synchronized** | **ReentrantLock** | |------------------------|-----------------------------------------------------|-------------------------------------------------------| | **实现原理** | JVM 内置监视器锁(Monitor)[^2] | 基于 AQS(AbstractQueuedSynchronizer)的 API 实现[^1] | | **锁类型** | 非公平锁(默认) | 支持公平锁非公平锁(通过构造函数指定)[^1] | | **锁获取方式** | 自动获取释放 | 需显式调用 `lock()` `unlock()` | | **底层依赖** | JVM 原生支持 | JDK 层面的 API 实现 | #### 二、功能特性对比 ```java // synchronized 示例 synchronized (obj) { // 临界区代码 } // ReentrantLock 示例 ReentrantLock lock = new ReentrantLock(); lock.lock(); try { // 临界区代码 } finally { lock.unlock(); // 必须显式释放 } ``` 1. **可中断性** - synchronized:线程阻塞时**不可中断** - ReentrantLock:支持 `lockInterruptibly()` 方法,允许中断等待中的线程[^1] ```java lock.lockInterruptibly(); try { // 可被 Thread.interrupt() 中断的临界区 } finally { lock.unlock(); } ``` 2. **超时控制** - synchronized:**不支持**获取锁超时 - ReentrantLock:支持 `tryLock(long timeout, TimeUnit unit)` 方法 ```java if (lock.tryLock(3, TimeUnit.SECONDS)) { try { /* 临界区 */ } finally { lock.unlock(); } } else { // 超时处理 } ``` 3. **条件变量** - synchronized:通过 `wait()`/`notify()` 实现单一等待队列 - ReentrantLock:支持多个 **Condition 对象**,实现分组唤醒[^3] ```java Condition condition = lock.newCondition(); // 线程A:condition.await(); // 线程B:condition.signal(); // 精确唤醒特定条件线程 ``` #### 三、性能差异 $$ \text{低并发场景} \rightarrow \begin{cases} \text{synchronized 优化(锁升级)} \rightarrow \text{性能接近} \\ \text{偏向锁/轻量级锁:开销低} \end{cases} $$ $$ \text{高并发场景} \rightarrow \begin{cases} \text{ReentrantLock} \rightarrow \text{更优的吞吐量} \\ \text{CAS 操作减少线程切换} \end{cases} $$ (JDK 1.6 后 synchronized 性能大幅提升,多数场景差距<5%[^2]) #### 四、异常处理 | **场景** | **synchronized** | **ReentrantLock** | |------------------------|---------------------------|----------------------------| | **同步块内异常** | 自动释放锁 | 需在 finally 中手动释放锁 | | **死锁风险** | 较高(不可中断) | 较低(支持尝试获取锁) | #### 五、适用场景对比 | **场景** | **推荐方案** | **原因** | |------------------------------|----------------------|------------------------------------| | 简单同步逻辑 | synchronized | 简洁安全,自动管理锁 | | 需要公平锁 | ReentrantLock | 构造函数指定公平策略[^1] | | 跨方法锁传递(锁链) | ReentrantLock | 可灵活控制锁边界 | | 分组唤醒等待线程 | ReentrantLock+Condition | 多个条件队列支持[^3] | | 高并发竞争优化 | ReentrantLock | CAS 减少线程切换 | > ⚠️ **关键陷阱**: > 使用 ReentrantLock 时**必须**在 finally 块中释放锁,否则会导致死锁: > ```java > lock.lock(); > try { > // 业务代码 > } finally { > lock.unlock(); // 必须确保执行 > } > ``` #### 六、最佳实践 1. **优先选择 synchronized**:简单同步需求(90%+场景) 2. **明确使用 ReentrantLock 的场景**: - 需要公平锁 - 需要尝试获取锁(tryLock) - 需要可中断的锁获取 - 需要分组唤醒线程 3. **监控工具支持**:ReentrantLock 可通过 `getOwner()` 等 API 获取锁状态(调试优势)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值