14人参与 • 2026-01-27 • Java
在多线程编程中,锁是保证数据一致性和线程安全的核心机制。java 提供了丰富的锁机制来应对不同的并发场景。本文将从锁的基本概念出发,详细讲解 java 中常见的锁类型、它们的使用场景、优缺点以及底层实现原理,并通过代码示例帮助读者深入理解。
锁是一种同步机制,用于控制多个线程对共享资源的访问。当一个线程获取锁后,其他线程必须等待该锁被释放才能继续执行,从而避免竞态条件(race condition)。
synchronized 关键字(内置锁)reentrantlock(可重入锁)public class counter {
private int count = 0;
// 同步方法,使用对象锁(this)
public synchronized void increment() {
count++;
}
// 同步代码块,使用指定对象锁
public void decrement() {
synchronized (this) {
count--;
}
}
public int getcount() {
return count;
}
}import java.util.concurrent.locks.reentrantlock;
public class reentrantexample {
private final reentrantlock lock = new reentrantlock();
private int count = 0;
public void increment() {
lock.lock();
try {
count++;
// 可以再次获取锁(可重入)
if (count == 1) {
system.out.println("thread " + thread.currentthread().getname() + " is re-entering the lock.");
}
} finally {
lock.unlock();
}
}
public int getcount() {
lock.lock();
try {
return count;
} finally {
lock.unlock();
}
}
}lockinterruptibly())。trylock(timeout))。unlock() 导致死锁。synchronized 复杂。import java.util.concurrent.locks.readwritelock;
import java.util.concurrent.locks.reentrantreadwritelock;
public class readwriteexample {
private final readwritelock lock = new reentrantreadwritelock();
private string data = "default";
// 读操作:多个线程可同时读
public string readdata() {
lock.readlock().lock();
try {
system.out.println(thread.currentthread().getname() + " is reading data: " + data);
return data;
} finally {
lock.readlock().unlock();
}
}
// 写操作:独占访问,其他读写均被阻塞
public void writedata(string newdata) {
lock.writelock().lock();
try {
system.out.println(thread.currentthread().getname() + " is writing data: " + newdata);
data = newdata;
} finally {
lock.writelock().unlock();
}
}
}import java.util.concurrent.atomic.atomicinteger;
public class atomiccounter {
private final atomicinteger count = new atomicinteger(0);
public void increment() {
count.incrementandget(); // cas 操作,原子递增
}
public int getcount() {
return count.get();
}
}atomicstampedreference 解决)。import java.util.concurrent.locks.stampedlock;
public class stampedlockexample {
private final stampedlock stampedlock = new stampedlock();
private double x, y;
// 乐观读:不加锁,先尝试读取,失败则升级为悲观读
public double distancefromorigin() {
long stamp = stampedlock.tryoptimisticread();
double currentx = x, currenty = y;
// 检查是否在读期间发生了写操作(版本变化)
if (!stampedlock.validate(stamp)) {
stamp = stampedlock.readlock();
try {
currentx = x;
currenty = y;
} finally {
stampedlock.unlockread(stamp);
}
}
return math.sqrt(currentx * currentx + currenty * currenty);
}
// 写操作:独占锁
public void move(double deltax, double deltay) {
long stamp = stampedlock.writelock();
try {
x += deltax;
y += deltay;
} finally {
stampedlock.unlockwrite(stamp);
}
}
}| 锁类型 | 适用场景 | 推荐程度 |
|---|---|---|
synchronized | 简单同步,小范围临界区 | ⭐⭐⭐⭐⭐ |
reentrantlock | 需要超时、中断、公平性控制 | ⭐⭐⭐⭐☆ |
reentrantreadwritelock | 读多写少的共享数据 | ⭐⭐⭐⭐☆ |
atomicxxx | 简单计数器、状态标志 | ⭐⭐⭐⭐⭐ |
stampedlock | 极高读性能需求,读多写少 | ⭐⭐⭐☆☆ |
synchronized:基于 jvm 的对象头(mark word)实现,通过 monitor 机制管理锁状态。reentrantlock:基于 aqs(abstractqueuedsynchronizer)实现,使用 cas+fifo 队列管理线程排队。stampedlock:基于版本戳(stamp)和状态位管理,支持乐观读。synchronized,除非有特殊需求。finally 块外调用 unlock(),防止死锁。stampedlock 适合高性能读场景,但需谨慎使用。锁是 java 并发编程的核心,合理选择锁类型能极大提升程序性能与稳定性。掌握不同锁的特点与适用场景,是成为一名高级 java 工程师的必经之路。希望本文能为你提供清晰的指导!
到此这篇关于java中锁的全面解析之类型、使用场景、优缺点及实现方式(示例代码)的文章就介绍到这了,更多相关java锁使用内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
您想发表意见!!点此发布评论
版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。
发表评论