📜  门| GATE CS 2020 |问题10(1)

📅  最后修改于: 2023-12-03 15:42:12.487000             🧑  作者: Mango

门 | GATE CS 2020 | 问题10

这是 GATE CS 2020 的第 10 道编程题,题目要求实现一个 lock() 和 unlock() 方法,在多线程环境下实现同步。

题目描述

实现一个 Door 类,该类有两个方法:

  1. lock(): 将 Door 锁定。如果 Door 已经被锁定,调用该方法的线程将被阻塞,直到 Door 解锁。
  2. unlock(): 将 Door 解锁,并唤醒等待中的所有线程。

实现的 Door 类需要支持多线程环境,同时需要保证线程安全。具体要求如下:

  1. 可以有多个线程调用 lock() 方法,但是只有一个线程可以持有 Door 的锁。
  2. 如果 Door 已经被锁定,则调用 lock() 方法的线程将被阻塞。当 Door 解锁时,其中一个被阻塞的线程将被唤醒并取得 Door 的锁。
  3. 当 Door 已经被锁定时,调用 unlock() 方法将唤醒等待中的一个线程并将 Door 解锁。如果当前没有线程在等待,则该方法不做任何操作。
解题思路

为了实现 Door 类,我们需要使用一个锁对象来保证线程安全。我们可以使用 ReentrantLock 类来实现锁机制,同时使用 Condition 对象来实现线程等待和唤醒逻辑。

在 Door 类的构造函数中创建一个 ReentrantLock 和一个 Condition 对象:

public Door() {
    lock = new ReentrantLock();
    condition = lock.newCondition();
}

在 lock() 方法中,我们首先获取锁,然后判断 Door 是否已被锁定。如果 Door 已经被锁定,则当前线程会阻塞在 condition 上,等待 unlock() 方法解锁 Door。

public void lock() {
    lock.lock();

    try {
        while (locked) {
            condition.await();
        }

        locked = true;
    } catch (InterruptedException e) {
        e.printStackTrace();
    } finally {
        lock.unlock();
    }
}

在 unlock() 方法中,我们同样需要获取锁,然后将 locked 设置为 false,表示 Door 已经解锁。然后,我们调用 signal() 方法唤醒等待中的一个线程。

public void unlock() {
    lock.lock();

    try {
        locked = false;
        condition.signal();
    } finally {
        lock.unlock();
    }
}
完整代码
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

public class Door {
    private ReentrantLock lock;
    private Condition condition;
    private boolean locked = false;

    public Door() {
        lock = new ReentrantLock();
        condition = lock.newCondition();
    }

    public void lock() {
        lock.lock();

        try {
            while (locked) {
                condition.await();
            }

            locked = true;
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    public void unlock() {
        lock.lock();

        try {
            locked = false;
            condition.signal();
        } finally {
            lock.unlock();
        }
    }
}
总结

本题要求实现一个同步锁,使用 ReentrantLock 和 Condition 对象来实现。在 lock() 方法中,使用条件变量来等待解锁;在 unlock() 方法中,使用 signal() 方法来唤醒等待中的一个线程。实现同步锁原理并不复杂,但是在多线程环境容易发生死锁或竞态条件等问题,需要注意代码安全性。