说明:Java & Go 并发编程序列的文章,根据每篇文章的主题或细分标题,分别演示 Java 和 Go 语言当中的相关实现。更多该系列文章请查看:Java & Go 并发编程系列
互斥锁,用来保证同一时刻只有一个线程进入临界区访问共享资源。在进入临界区之前,需要先获得锁,成功获得锁之后,其他线程因为无法获得锁所以不能进入该临界区。而访问结束之后,需要及时解锁,以便其他线程获取。
以上提到的线程在 Go 语言指 Goroutine。
以下代码使用了 CountDownLatch 和 sync.WaitGroup,并非本文的重点,关于两者的用法请回顾前文:等待一组并发任务完成——CountDownLatch VS sync.WaitGroup
代码场景:假设有一台自动售卖机,售卖和补货操作不能同一时间进行。即:
- 当用户在购物时,就不能执行补货操作;
- 当执行补货操作时,用户也不能购物;
- 如果有多个用户需要购物,也只能依次执行。
以下代码场景模拟5个用户购物和1个补货员补货的操作。
「Java」ReentrantLock
ReentrantLock为 Java 中 Lock 的默认实现,关键方法为 lock()
和 unlock()
。
// VendingMachine 表示自动售卖机
static class VendingMachine {
// 使用锁来保证,售卖和补货不能同时进行
private final ReentrantLock lock;
public VendingMachine() {
this.lock = new ReentrantLock();
}
// 售卖
public void sale() {
lock.lock();// 获得锁之后才能往下执行
try {
System.out.printf("[%s] 开始购物...\n",
Thread.currentThread().getName());
TimeUnit.MILLISECONDS.sleep(200);
System.out.printf("[%s] 购物完成.\n",
Thread.currentThread().getName());
} catch (InterruptedException e) {