Java中的ReentrantLock是一种高级的并发锁机制,它比synchronized关键字更加灵活、功能更加强大。ReentrantLock提供了比synchronized更多的锁定操作和更细粒度的控制,可以更好地支持高级并发系统。
以下是ReentrantLock的详细使用攻略:
1. 导入ReentrantLock类
首先需要在Java项目中导入ReentrantLock类,可以使用以下代码:
import java.util.concurrent.locks.ReentrantLock;
2. 创建ReentrantLock对象
可以使用以下代码创建ReentrantLock对象:
ReentrantLock lock = new ReentrantLock();
3. 加锁和解锁
使用lock()方法加锁,使用unlock()方法解锁。在锁定和解锁之间的代码是受保护的,只有一个线程可以访问这部分代码。
lock.lock();
try {
//代码块
} finally {
lock.unlock();
}
在使用ReentrantLock时,必须使用try-finally结构来确保解锁。这是非常重要的,因为如果在代码块中发生异常,并且没有解锁,那么其他线程可能会被永久阻塞。
4. 条件变量
ReentrantLock还提供了一个条件变量机制,可以使用await()、signal()、signalAll()方法实现。这个机制与Object.wait()和Object.notify()方法的作用类似。
Condition condition = lock.newCondition();
lock.lock();
try {
while (someCondition) {
condition.await();
}
} finally {
lock.unlock();
}
在这个例子中,线程会在条件someCondition满足之前一直等待。当条件满足后,线程会被唤醒,并继续执行。
示例1:ReentrantLock控制并发执行
class MyCounter {
private int count = 0;
private ReentrantLock lock = new ReentrantLock();
public void increment() {
lock.lock();
try {
count++;
} finally {
lock.unlock();
}
}
public void decrement() {
lock.lock();
try {
count--;
} finally {
lock.unlock();
}
}
public int getCount() {
return count;
}
}
public class Main {
public static void main(String[] args) {
MyCounter counter = new MyCounter();
Runnable incrementRunnable = () -> {
for (int i = 0; i < 1000000; i++) {
counter.increment();
}
};
Runnable decrementRunnable = () -> {
for (int i = 0; i < 1000000; i++) {
counter.decrement();
}
};
Thread incrementThread1 = new Thread(incrementRunnable);
Thread incrementThread2 = new Thread(incrementRunnable);
Thread decrementThread1 = new Thread(decrementRunnable);
Thread decrementThread2 = new Thread(decrementRunnable);
incrementThread1.start();
incrementThread2.start();
decrementThread1.start();
decrementThread2.start();
try {
incrementThread1.join();
incrementThread2.join();
decrementThread1.join();
decrementThread2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(counter.getCount());
}
}
在这个例子中,使用ReentrantLock来控制一个计数器的并发执行,可以看到锁机制可以有效避免竞态条件的发生,保证了计数器的正确性。
示例2:使用ReentrantLock实现生产者和消费者模式
class Buffer {
private LinkedList<Object> buffer = new LinkedList<>();
private int maxSize = 10;
private ReentrantLock lock = new ReentrantLock();
private Condition notFull = lock.newCondition();
private Condition notEmpty = lock.newCondition();
public void put(Object obj) throws InterruptedException {
lock.lock();
try {
while (buffer.size() == maxSize) {
notFull.await();
}
buffer.add(obj);
notEmpty.signal();
} finally {
lock.unlock();
}
}
public Object get() throws InterruptedException {
lock.lock();
try {
while (buffer.size() == 0) {
notEmpty.await();
}
Object obj = buffer.remove();
notFull.signal();
return obj;
} finally {
lock.unlock();
}
}
}
public class Main {
public static void main(String[] args) {
Buffer buffer = new Buffer();
Runnable producer = () -> {
for (int i = 0; i < 100; i++) {
try {
buffer.put(i);
System.out.println(Thread.currentThread().getName() + ": put " + i);
Thread.sleep((long) (Math.random() * 100));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
Runnable consumer = () -> {
for (int i = 0; i < 100; i++) {
try {
Object obj = buffer.get();
System.out.println(Thread.currentThread().getName() + ": get " + obj);
Thread.sleep((long) (Math.random() * 100));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
Thread producer1 = new Thread(producer, "producer1");
Thread producer2 = new Thread(producer, "producer2");
Thread consumer1 = new Thread(consumer, "consumer1");
Thread consumer2 = new Thread(consumer, "consumer2");
producer1.start();
producer2.start();
consumer1.start();
consumer2.start();
}
}
在这个例子中,使用ReentrantLock和条件变量实现了生产者和消费者模式,确保了缓冲区不会出现过多的生产者或消费者,从而达到了线程间交互的目的。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:java ReentrantLock并发锁使用详解 - Python技术站