java中锁
时间: 2025-05-28 08:47:03 浏览: 25
### Java 中的锁机制概述
Java 提供了多种锁机制以支持多线程环境下的同步操作。这些锁机制主要包括内置锁(synchronized 关键字)、显示锁(ReentrantLock 类)以及一些高级特性如读写锁(ReadWriteLock)。以下是关于它们的具体介绍:
---
### 内置锁(Intrinsic Lock)
Java 的 synchronized 关键字提供了一种简单的方式来进行线程间的同步。每个对象都有一个与之关联的监视器(monitor),当一个线程进入由 synchronized 修饰的方法或代码块时,它会自动获得该对象的监视器锁。
```java
public class Counter {
private int count = 0;
public synchronized void increment() {
count++;
}
public synchronized int getCount() {
return count;
}
}
```
上述代码展示了如何使用 synchronized 方法来确保多个线程不会同时修改 `count` 变量[^1]。
---
### 显示锁(Explicit Lock)
相比于内置锁,显示锁提供了更大的灵活性。`ReentrantLock` 是最常用的显示锁实现之一,它可以手动控制锁的获取和释放,并且支持可中断锁等待、超时尝试等功能。
#### 使用示例
```java
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class Worker {
private final Lock lock = new ReentrantLock();
private int value = 0;
public void updateValue(int newValue) throws InterruptedException {
boolean isLocked = false;
try {
isLocked = lock.tryLock(1000, java.util.concurrent.TimeUnit.MILLISECONDS);
if (isLocked) {
value = newValue;
} else {
System.out.println("Failed to acquire the lock.");
}
} finally {
if (isLocked) {
lock.unlock();
}
}
}
public int getValue() {
lock.lock();
try {
return value;
} finally {
lock.unlock();
}
}
}
```
此代码片段演示了如何利用 `tryLock()` 方法在一定时间内尝试获取锁,如果无法获取,则可以选择其他逻辑路径[^1]。
---
### 偏向锁(Biased Locking)
偏向锁是一种优化技术,旨在减少无竞争情况下锁的操作开销。它的基本思想是在第一次访问某个锁时将其绑定到当前线程,后续再次访问时不需额外验证即可直接执行。
然而,一旦检测到有其他线程尝试获取同一个锁,JVM 将撤销偏向锁并升级为轻量级锁甚至重量级锁。这一过程发生在全局安全点处,因为需要暂停所有活动线程以重新评估锁的状态[^3]。
---
### 轻量级锁(Lightweight Locking)
轻量级锁通过自旋的方式来避免线程切换带来的性能损失。具体来说,当第一个线程请求锁时,它会在栈帧中保存指向锁记录的信息;第二个线程到达时发现锁已被占用,则启动循环不断检查锁是否可用。只有当自旋次数达到上限仍未能成功时,才会退化成重量级锁[^4]。
---
### 解决 ABA 问题
在高并发场景下可能出现一种称为 ABA 的现象:某一变量先后经历了两次相同值的变化,但其间可能发生了不可忽略的动作。为此引入了带版本号的原子引用类 `AtomicStampedReference` 来加以防范[^5]。
```java
import java.util.concurrent.atomic.AtomicStampedReference;
public class ABADemo {
static AtomicStampedReference<Integer> atomicRef =
new AtomicStampedReference<>(100, 0);
public static void main(String[] args) {
new Thread(() -> {
int stamp = atomicRef.getStamp();
try {Thread.sleep(1);} catch (Exception ignored){}
atomicRef.compareAndSet(100, 101, stamp, stamp + 1);
atomicRef.compareAndSet(101, 100, stamp + 1, stamp + 2);
}).start();
new Thread(() -> {
int stamp = atomicRef.getStamp();
try {Thread.sleep(2);} catch (Exception ignored){}
boolean result = atomicRef.compareAndSet(100, 101, stamp, stamp + 1);
System.out.println(result ? "Success" : "Failure");
}).start();
}
}
```
以上例子表明即使目标数值看似未变,但由于附加了时间戳标记,依然能有效区分实际发生的改动序列[^5]。
---
### 高效实践建议
- 对于短期锁定需求优先考虑内置锁;
- 如果涉及复杂业务流程推荐选用显式锁以便更好地掌控资源分配状况;
- 注意合理配置锁粒度大小以免造成不必要的争用瓶颈。
---
阅读全文
相关推荐

















