Java锁机制详解
什么是锁机制
锁机制是Java并发编程中保证线程安全的核心手段,通过互斥访问共享资源来避免竞态条件。
synchronized关键字
方法锁
public class SynchronizedMethodDemo {
private int count = 0;
public synchronized void increment() {
count++;
}
public synchronized int getCount() {
return count;
}
public static void main(String[] args) throws InterruptedException {
SynchronizedMethodDemo demo = new SynchronizedMethodDemo();
Runnable task = () -> {
for (int i = 0; i < 10000; i++) {
demo.increment();
}
};
Thread t1 = new Thread(task);
Thread t2 = new Thread(task);
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println("最终计数: " + demo.getCount());
}
}
代码块锁
public class SynchronizedBlockDemo {
private final Object lock = new Object();
private int balance = 1000;
public void withdraw(int amount) {
synchronized (lock) {
if (balance >= amount) {
balance -= amount;
System.out.println("取款成功,余额: " + balance);
} else {
System.out.println("余额不足");
}
}
}
public void deposit(int amount) {
synchronized (lock) {
balance += amount;
System.out.println("存款成功,余额: " + balance);
}
}
}
静态方法锁
public class StaticSyncDemo {
private static int staticCount = 0;
public static synchronized void staticIncrement() {
staticCount++;
}
public static synchronized int getStaticCount() {
return staticCount;
}
}
ReentrantLock
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class ReentrantLockDemo {
private final Lock lock = new ReentrantLock();
private int balance = 1000;
public void transfer(int amount) {
lock.lock();
try {
if (balance >= amount) {
balance -= amount;
System.out.println(Thread.currentThread().getName() +
"转出: " + amount + ", 余额: " + balance);
}
} finally {
lock.unlock();
}
}
public static void main(String[] args) throws InterruptedException {
ReentrantLockDemo demo = new ReentrantLockDemo();
Runnable task = () -> {
for (int i = 0; i < 100; i++) {
demo.transfer(10);
}
};
Thread t1 = new Thread(task, "线程A");
Thread t2 = new Thread(task, "线程B");
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println("最终余额: " + demo.balance);
}
}
可中断锁
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class InterruptibleLockDemo {
private final Lock lock = new ReentrantLock();
public void doWork() {
lock.lock();
try {
System.out.println("获取锁,开始工作");
Thread.sleep(5000);
} catch (InterruptedException e) {
System.out.println("工作被中断");
} finally {
lock.unlock();
System.out.println("释放锁");
}
}
public static void main(String[] args) throws InterruptedException {
InterruptibleLockDemo demo = new InterruptibleLockDemo();
Thread worker = new Thread(demo::doWork);
worker.start();
Thread.sleep(1000);
System.out.println("中断工作线程");
worker.interrupt();
worker.join();
}
}
读写锁
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
public class ReadWriteLockDemo {
private final ReadWriteLock rwLock = new ReentrantReadWriteLock();
private int data = 0;
public int read() {
rwLock.readLock().lock();
try {
System.out.println(Thread.currentThread().getName() +
"读取数据: " + data);
return data;
} finally {
rwLock.readLock().unlock();
}
}
public void write(int value) {
rwLock.writeLock().lock();
try {
data = value;
System.out.println(Thread.currentThread().getName() +
"写入数据: " + data);
} finally {
rwLock.writeLock().unlock();
}
}
public static void main(String[] args) throws InterruptedException {
ReadWriteLockDemo demo = new ReadWriteLockDemo();
Runnable reader = () -> {
for (int i = 0; i < 3; i++) {
demo.read();
}
};
Runnable writer = () -> {
for (int i = 0; i < 3; i++) {
demo.write(i * 100);
}
};
Thread[] readers = new Thread[3];
for (int i = 0; i < 3; i++) {
readers[i] = new Thread(reader, "读线程" + i);
}
Thread writerThread = new Thread(writer, "写线程");
for (Thread r : readers) {
r.start();
}
writerThread.start();
for (Thread r : readers) {
r.join();
}
writerThread.join();
}
}
条件锁
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class ConditionLockDemo {
private final Lock lock = new ReentrantLock();
private final Condition notEmpty = lock.newCondition();
private final Condition notFull = lock.newCondition();
private final int[] buffer = new int[5];
private int count = 0;
public void produce(int item) throws InterruptedException {
lock.lock();
try {
while (count == buffer.length) {
notFull.await();
}
buffer[count++] = item;
System.out.println("生产: " + item);
notEmpty.signalAll();
} finally {
lock.unlock();
}
}
public int consume() throws InterruptedException {
lock.lock();
try {
while (count == 0) {
notEmpty.await();
}
int item = buffer[--count];
System.out.println("消费: " + item);
notFull.signalAll();
return item;
} finally {
lock.unlock();
}
}
}
锁的最佳实践
- 优先使用synchronized,简单场景足够
- 需要高级功能时使用ReentrantLock
- 读多写少场景使用ReadWriteLock
- 始终在finally中释放锁
- 避免嵌套锁导致死锁
总结
Java锁机制是保证线程安全的重要手段。理解synchronized和ReentrantLock的使用场景,能帮助你编写安全高效的并发代码。