简体   繁体   English

简单的LinkedList和队列同步

[英]Simple LinkedList and Queue synchronization

For a college Assignment I need to implement part of a hospital patient waiting system.The system uses a Collection of Patients on a waiting list, and a set of Patients registered for an operation during a specified period, for example this year. 对于大学作业,我需要实施医院病人等待系统的一部分。系统使用等待名单上的患者集合,以及在特定时期(例如今年)注册操作的一组患者。

I have implemented the method required as below, using a HashSet and a LinkedList. 我使用HashSet和LinkedList实现了如下所需的方法。 The method is almost completely synchronized, so I am wondering if there is a more efficient implementation with less synchronization, or perhaps more granular read write synchronization using locks? 该方法几乎完全同步,所以我想知道是否有更低效的实现同步更少,或者使用锁更精细的读写同步?

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;
    }
}

You only have some of your code here, but your synchronization looks good. 你这里只有一些代码,但你的同步看起来不错。

FYI, your LinkedList.contains takes O(n) . 仅供参考,您的LinkedList.contains需要O(n) I would do one of the following 我会做以下其中一项

  1. Use a LinkedHashSet which has constant lookup, but maintains the order. 使用具有常量查找但仍保持顺序的LinkedHashSet However, depending on your use of this later, this might not be satisfactory. 但是,根据您以后的使用情况,这可能不会令人满意。

  2. Use a HashSet to augment your LinkedList . 使用HashSet来扩充LinkedList Use the LinkedList except when checking .contains() . 除了检查.contains()时,请使用LinkedList

You could consider a read/write lock... but choosing that depends on your expectations of how often users will be only reading the collections, versus reading and writing. 您可以考虑读/写锁...但选择这取决于您对用户阅读集合的频率以及阅读和写作的期望。

A. How many times users try to add a patient that already exists (read) A.用户尝试添加已存在的患者的次数(阅读)

B. How often you'll be reading the lists from another part of your application not shown above (read) B.您经常阅读上面未显示的应用程序其他部分的列表(阅读)

C. How many times users successfully add a patient (read + write) C.用户成功添加患者的次数(读取+写入)

If (A + B) is huge when compared to C, consider a read/write lock like java.util.concurrent.locks.ReentrantReadWriteLock . 如果与C相比(A + B)很大,请考虑像java.util.concurrent.locks.ReentrantReadWriteLock这样的读/写锁。 Call readLock() to start your reading (which only blocks writers, not other readers), and if necessary, release the read lock and call writeLock() to escalate to writing (thereby blocking all other reads and writes). 调用readLock()开始读取(只阻止编写器,而不是其他读取器),如果需要,释放读锁定并调用writeLock()以升级到写入(从而阻止所有其他读取和写入)。 After obtaining the write lock, be sure to re-check your assertions you checked during the read-lock stage. 获得写锁定后,请务必重新检查在读锁定阶段检查的断言。

That aside, your existing synchronization looks fine. 除此之外,您现有的同步看起来很好。

One idea would be a ReadWriteLock. 一个想法是ReadWriteLock。 Because in this part of the code: 因为在这部分代码中:

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);
}

you are blocking access to the entire list, even though just reading on the list wouldn't cause any threading issues, but then you need to lock just in case the instruction could write later on. 您阻止访问整个列表,即使只是读取列表不会导致任何线程问题,但是您需要锁定以防以后指令可以写入。 This is solved by the ReadWriteLock, by granting unlimited read access unless someone actually wants to write. 这是由ReadWriteLock解决的,通过授予无限制的读访问权限,除非有人真正想写。 This could be implemented like this: 这可以像这样实现:

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();
}

Now if many threads only need to read, but rarely write, this will increase the speed of your application. 现在,如果许多线程只需要读取,但很少写入,这将提高应用程序的速度。 If almost all threads that read as well write, this would actually slow things down, as you not only need to check twice, but as well need to lock twice. 如果几乎所有读取的线程都写入,这实际上会减慢速度,因为您不仅需要检查两次,还需要锁定两次。 In addition synchronized is faster than lock. 另外,synchronized比锁更快。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM