简单链接列表和队列同步

时间:2013-11-13 02:22:18

标签: java multithreading concurrency

对于大学作业,我需要实施医院病人等待系统的一部分。系统使用等待名单上的患者集合,以及在特定时期(例如今年)注册操作的一组患者。

我已经使用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;
    }
}

3 个答案:

答案 0 :(得分:1)

您这里只有一些代码,但您的同步看起来不错。

仅供参考,您的LinkedList.contains需要O(n)。我会做以下其中一个

  1. 使用具有常量查找的LinkedHashSet,但保持顺序。但是,根据您以后的使用情况,这可能不太令人满意。

  2. 使用HashSet来扩充您的LinkedList。检查LinkedList

  3. 时,请使用.contains()

答案 1 :(得分:1)

您可以考虑读/写锁...但选择这取决于您对用户只阅读收藏的频率的期望,而不是阅读和写作。

一个。用户尝试添加已存在的患者的次数(阅读)

B中。您是否经常阅读上面未显示的应用程序其他部分的列表(阅读)

℃。用户成功添加患者的次数(读取+写入)

如果与C相比(A + B)很大,请考虑像java.util.concurrent.locks.ReentrantReadWriteLock这样的读/写锁定。调用readLock()开始读取(只阻止编写器,而不是其他读取器),如果需要,释放读锁定并调用writeLock()以升级到写入(从而阻止所有其他读取和写入)。获得写锁定后,请务必重新检查在读锁定阶段检查的断言。

除此之外,您现有的同步看起来还不错。

答案 2 :(得分:0)

一个想法是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比锁定更快。