📅  最后修改于: 2023-12-03 15:28:42.289000             🧑  作者: Mango
这是一道GATE-CS-2004的考题,考察的是关于并发编程的知识,下面将会对该问题进行详细介绍和分析。
某市政中央公园的入口和出口都装有转门。拜访者在入口部分向门内传送一个硬币,触发转门的开启动作,然后继续工作——如果他使用的硬币是指定的硬币。一旦一个访问者在门上打印了自己的指纹,他的护照上会被附加一个标记作为有效的拜访者并允许离开。门可以同时容纳10个有资格的人被容纳在等着通过或离开。如果有超过10个参观者在等候,其他的访问者必须等待,直到有人通过。离开门由一个类似于进门的机制控制;在离开时,访问者再次送出硬币,并再次打印自己的指纹。门将清理每个过程中的未确认的参观者。
请设计一个并发控制方案,使这个门满足这样的规则:
为了实现该控制方案,我们需要设计一个管理门的类,这个类需要控制一些重要资源,如门本身、能够通过的人数、正在等待进门的人数等。同时,还需要保证并发控制。
下面是可能的类设计和实现,注释对应着代码:
class DoorManager {
private int numVisitorsInside; // 当前门内已经通过的游客人数
private int numVisitorsAllowed; // 可以同时容纳的游客最大人数
private int numVisitorsWaiting; // 正在等待进入门内的游客总数
private Object doorLock; // 门锁,用于控制并发
private ArrayList<Integer> fingerprints; // 已经通过门的游客的指纹数据,仅限于进入门的人员
public DoorManager(int maxCapacity) {
numVisitorsInside = 0;
numVisitorsAllowed = maxCapacity;
numVisitorsWaiting = 0;
doorLock = new Object();
fingerprints = new ArrayList<>();
}
public boolean enterGate(int fingerprint) {
synchronized (doorLock) { // 可重入锁,确保并发控制
if (fingerprints.contains(fingerprint)) { // 判断是否已经进入过门
return false; // 如果已经进入过门,则无法再次进入门
}
if (numVisitorsInside >= numVisitorsAllowed) { // 如果门内已经有人数超过了门的能力
numVisitorsWaiting++; // 将等候人数+1,等到有人出门再重新计算
try {
doorLock.wait(); // 等待信号
} catch (InterruptedException e) {}
}
numVisitorsInside++; // 注册入门
fingerprints.add(fingerprint);
return true; // 允许进入门
}
}
public boolean exitGate(int fingerprint) {
synchronized (doorLock) { // 可重入锁
if (!fingerprints.contains(fingerprint)) { // 如果没有记录该游客进门的指纹
return false; // 无法结束这次入门,也就无法出门
}
fingerprints.remove(new Integer(fingerprint)); // 移除指纹信息
numVisitorsInside--; // 减去门内人数
if (numVisitorsInside < numVisitorsAllowed && numVisitorsWaiting > 0) {
numVisitorsWaiting--; // 有等候中的游客进入了,将等候人数-1
doorLock.notify(); // 通知等待中的游客进门
}
return true; // 允许出门
}
}
}
上述代码可在多线程环境下安全执行,并允许遵守上述规则的访问控制。请确保按照上述指南在单元测试中验证实现,以确保其正确性。