本文目录导读:

我将为您详细介绍偏向锁的概念、原理和实战案例。
偏向锁概述
什么是偏向锁?
偏向锁是Java synchronized关键字的一种优化机制,核心思想是:当一个线程第一次获取锁时,会在对象头和栈帧的锁记录中记录该线程ID,后续该线程再次进入同步块时,无需再进行CAS操作,直接进入。
适用场景
- 只有一个线程访问同步块
- 线程交替执行但竞争不激烈
实战案例
案例1:基础偏向锁演示
public class BiasedLockBasic {
// 创建对象作为锁
private static final Object lock = new Object();
public static void main(String[] args) throws InterruptedException {
// JVM默认启动4秒后开启偏向锁,这里手动延迟
Thread.sleep(5000);
Runnable task = () -> {
synchronized (lock) {
System.out.println(Thread.currentThread().getName()
+ " 获取偏向锁: " + LockHelper.getLockState(lock));
}
};
// 同一个线程多次获取锁
Thread thread = new Thread(() -> {
for (int i = 0; i < 5; i++) {
synchronized (lock) {
System.out.println("第" + (i+1) + "次获取:"
+ LockHelper.getLockState(lock));
}
}
}, "单线程");
thread.start();
Thread.sleep(1000);
// 锁状态查看
System.out.println("最终锁状态: " + LockHelper.getLockState(lock));
}
}
// 锁状态查看工具类
class LockHelper {
public static String getLockState(Object obj) {
// 使用JOL工具获取对象头信息
return org.openjdk.jol.info.ClassLayout.parseInstance(obj)
.toPrintable();
}
}
案例2:偏向锁升级演示
public class BiasedLockUpgrade {
private static final Object lock = new Object();
public static void main(String[] args) throws InterruptedException {
Thread.sleep(5000); // 等待偏向锁启动
// 阶段1:单独一个线程获取锁(偏向锁)
System.out.println("=== 阶段1:单线程获取锁 ===");
Thread thread1 = new Thread(() -> {
synchronized (lock) {
System.out.println("线程1获取锁");
System.out.println("锁对象信息: " +
org.openjdk.jol.info.ClassLayout.parseInstance(lock).toPrintable());
}
// 线程1结束,但偏向锁仍然存在
System.out.println("线程1执行完毕,锁状态: ");
System.out.println(org.openjdk.jol.info.ClassLayout.parseInstance(lock).toPrintable());
}, "线程1");
thread1.start();
thread1.join();
Thread.sleep(1000);
// 阶段2:另一个线程尝试获取锁(锁升级为轻量级锁)
System.out.println("\n=== 阶段2:第二个线程获取锁 ===");
Thread thread2 = new Thread(() -> {
synchronized (lock) {
System.out.println("线程2获取锁");
System.out.println("锁对象信息: " +
org.openjdk.jol.info.ClassLayout.parseInstance(lock).toPrintable());
}
}, "线程2");
thread2.start();
thread2.join();
// 阶段3:多个线程竞争(升级为重量级锁)
System.out.println("\n=== 阶段3:多线程竞争 ===");
// 制造竞争
Thread[] threads = new Thread[3];
CountDownLatch latch = new CountDownLatch(3);
for (int i = 0; i < 3; i++) {
threads[i] = new Thread(() -> {
synchronized (lock) {
System.out.println(Thread.currentThread().getName() + " 获取锁");
try {
Thread.sleep(100); // 保持持有锁
} catch (InterruptedException e) {
e.printStackTrace();
}
}
latch.countDown();
}, "竞争线程" + i);
threads[i].start();
}
latch.await();
System.out.println("最终锁状态: ");
System.out.println(org.openjdk.jol.info.ClassLayout.parseInstance(lock).toPrintable());
}
}
案例3:偏向锁批量撤销
public class BiasedLockBatchRevocation {
public static void main(String[] args) throws InterruptedException {
Thread.sleep(5000);
// 创建多个锁对象
List<Object> locks = new ArrayList<>();
for (int i = 0; i < 30; i++) {
locks.add(new Object());
}
// 第一个线程获取所有锁(偏向锁)
System.out.println("=== 第一个线程获取所有锁 ===");
Thread thread1 = new Thread(() -> {
for (Object lock : locks) {
synchronized (lock) {
// 不做任何操作
}
}
}, "偏向线程");
thread1.start();
thread1.join();
// 第二个线程获取所有锁(触发批量撤销)
System.out.println("=== 第二个线程获取所有锁 ===");
Thread thread2 = new Thread(() -> {
for (int i = 0; i < locks.size(); i++) {
Object lock = locks.get(i);
synchronized (lock) {
System.out.println("锁 " + i + " 状态: " +
org.openjdk.jol.info.ClassLayout.parseInstance(lock).toPrintable().split("\n")[2]);
}
}
}, "撤销线程");
thread2.start();
thread2.join();
// 查看批量撤销后新对象的状态
System.out.println("=== 批量撤销后新创建的对象 ===");
Object newLock = new Object();
System.out.println("新对象锁状态: " +
org.openjdk.jol.info.ClassLayout.parseInstance(newLock).toPrintable());
}
}
案例4:哈希码与偏向锁
public class BiasedLockHashCode {
public static void main(String[] args) throws InterruptedException {
Thread.sleep(5000);
Object lock = new Object();
System.out.println("初始状态(无偏向锁): ");
System.out.println(org.openjdk.jol.info.ClassLayout.parseInstance(lock).toPrintable());
// 获取哈希码会撤销偏向锁
System.out.println("调用hashCode后: ");
int hash = lock.hashCode();
System.out.println("哈希值: " + hash);
System.out.println(org.openjdk.jol.info.ClassLayout.parseInstance(lock).toPrintable());
// 偏向锁与hashCode不能共存
Object lock2 = new Object();
Thread thread = new Thread(() -> {
synchronized (lock2) {
System.out.println("获取偏向锁: ");
System.out.println(org.openjdk.jol.info.ClassLayout.parseInstance(lock2).toPrintable());
// 在持有偏向锁时调用hashCode
System.out.println("偏向锁时调用hashCode: ");
System.out.println("hash值: " + lock2.hashCode());
System.out.println(org.openjdk.jol.info.ClassLayout.parseInstance(lock2).toPrintable());
}
});
thread.start();
thread.join();
}
}
运行配置
需要添加JVM参数和依赖:
<!-- Maven依赖 -->
<dependency>
<groupId>org.openjdk.jol</groupId>
<artifactId>jol-core</artifactId>
<version>0.16</version>
</dependency>
# JVM运行参数 # 开启偏向锁(JDK8默认开启,但延迟4秒) -XX:+UseBiasedLocking -XX:BiasedLockingStartupDelay=0 # 或者完全关闭偏向锁 -XX:-UseBiasedLocking # 设置批量撤销阈值 -XX:BiasedLockingBulkRevokeThreshold=20 -XX:BiasedLockingBulkRebiasThreshold=40
性能测试对比
public class BiasedLockPerformance {
public static void main(String[] args) throws InterruptedException {
Thread.sleep(5000);
int threadCount = 1; // 单线程场景
int iterations = 1_000_000;
// 测试偏向锁
long start = System.currentTimeMillis();
runSingleThread(iterations);
long biasedLockTime = System.currentTimeMillis() - start;
System.out.println("偏向锁耗时: " + biasedLockTime + "ms");
}
private static void runSingleThread(int iterations) {
Object lock = new Object();
for (int i = 0; i < iterations; i++) {
synchronized (lock) {
// 模拟业务操作
int x = i + 1;
}
}
}
}
关键要点总结
偏向锁的优势
- 减少CAS操作:同一线程重复获取锁时无需CAS
- 提高单线程性能:和未加锁性能基本一致
- 适合读多写少:多个线程读取但只有一个写入的场景
偏向锁的代价
- 批量撤销开销:当锁竞争激烈时会频繁撤销
- 暂停所有线程:批量撤销时需要STW
- 内存占用:每个对象头都需要存储偏向线程ID
最佳实践建议
- JDK8:默认开启偏向锁,但有4秒延迟
- JDK15:默认禁用偏向锁
- 高竞争场景:考虑使用 -XX:-UseBiasedLocking 关闭
- 单线程场景:可以设置偏向锁延迟为0
常见问题
// 问题1:偏向锁被另一个线程获取
public class BiasedLockQuestion {
public static void main(String[] args) throws InterruptedException {
Thread.sleep(5000);
Object lock = new Object();
// 线程A获取偏向锁
Thread a = new Thread(() -> {
synchronized (lock) {
System.out.println("线程A持有锁");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {}
}
}, "A");
a.start();
a.join();
// 线程B尝试获取(触发撤销)
Thread b = new Thread(() -> {
synchronized (lock) {
System.out.println("线程B获取锁(偏向锁撤销)");
}
}, "B");
b.start();
b.join();
// 线程C再次获取(锁已升级为轻量级)
Thread c = new Thread(() -> {
synchronized (lock) {
System.out.println("线程C获取锁(已升级)");
}
}, "C");
c.start();
c.join();
}
}
希望这些案例能帮助您深入理解偏向锁的工作机制和实际应用场景!
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播