[英]Simple LinkedList and Queue synchronization
对于大学作业,我需要实施医院病人等待系统的一部分。系统使用等待名单上的患者集合,以及在特定时期(例如今年)注册操作的一组患者。
我使用HashSet和LinkedList实现了如下所需的方法。 该方法几乎完全同步,所以我想知道是否有更低效的实现同步更少,或者使用锁更精细的读写同步?
public Class OperationPeriod {
...
private Set<Patient> registeredPatients=new HashSet<Patient>();
private Collection<Patient> waitingListPatients=new LinkedList<Patient>();
private int capacity;
...
public boolean bookOperation(Patient patient){
if (!Operation.checkHasMetRequirements(patient)) {
return false;
}
//patient could already be registered
synchronized(this) {
if(registeredPatients.contains(patient)) {
return true;
}
if(waitingListPatients.contains(patient) ) {
return false;
}
//Not already registered so register or add to waiting list
return addPatient(patient);
}
}
private boolean addPatient(Patient patient) {
if(registeredPatients.size() < capacity) {
registeredPatients.add(patient);
return true;
}
else {
waitingListPatients.add(patient);
return false;
}
}
你这里只有一些代码,但你的同步看起来不错。
仅供参考,您的LinkedList.contains
需要O(n)
。 我会做以下其中一项
使用具有常量查找但仍保持顺序的LinkedHashSet
。 但是,根据您以后的使用情况,这可能不会令人满意。
使用HashSet
来扩充LinkedList
。 除了检查.contains()
时,请使用LinkedList
。
您可以考虑读/写锁...但选择这取决于您对用户阅读集合的频率以及阅读和写作的期望。
A.用户尝试添加已存在的患者的次数(阅读)
B.您经常阅读上面未显示的应用程序其他部分的列表(阅读)
C.用户成功添加患者的次数(读取+写入)
如果与C相比(A + B)很大,请考虑像java.util.concurrent.locks.ReentrantReadWriteLock
这样的读/写锁。 调用readLock()开始读取(只阻止编写器,而不是其他读取器),如果需要,释放读锁定并调用writeLock()以升级到写入(从而阻止所有其他读取和写入)。 获得写锁定后,请务必重新检查在读锁定阶段检查的断言。
除此之外,您现有的同步看起来很好。
一个想法是ReadWriteLock。 因为在这部分代码中:
synchronized(this) {
if(registeredPatients.contains(patient)) {
return true;
}
if(waitingListPatients.contains(patient) ) {
return false;
}
//Not already registered so register or add to waiting list
return addPatient(patient);
}
您阻止访问整个列表,即使只是读取列表不会导致任何线程问题,但是您需要锁定以防以后指令可以写入。 这是由ReadWriteLock解决的,通过授予无限制的读访问权限,除非有人真正想写。 这可以像这样实现:
lock.readLock().lock();
try {
if(registeredPatients.contains(patient)) {
return true;
}
if(waitingListPatients.contains(patient) ) {
return false;
}
} finally {
lock.readLock().unlock();
}
//Not already registered so register or add to waiting list
lock.writeLock().lock();
try {
// need to re-check here, as the list could have been changed in between
if(registeredPatients.contains(patient)) {
return true;
}
if(waitingListPatients.contains(patient) ) {
return false;
}
return addPatient(patient);
} finally {
lock.writeLock().unlock();
}
现在,如果许多线程只需要读取,但很少写入,这将提高应用程序的速度。 如果几乎所有读取的线程都写入,这实际上会减慢速度,因为您不仅需要检查两次,还需要锁定两次。 另外,synchronized比锁更快。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.