简体   繁体   English

如何使循环队列完全线程安全

[英]How to make a circular queue completely thread safe

At the minute I have just added synchronized to the majority of methods as it appears that without it, these methods with not be thread safe. 目前,我刚刚将同步添加到大多数方法中,因为如果没有同步,这些方法将不是线程安全的。 Is there anything else that I need to implement to ensure that it is thread safe. 还有什么我需要实现的,以确保它是线程安全的。

Also, is there a better way to go about this. 此外,还有更好的方法可以解决此问题。 At the minute only one thread will be able to use circular queue at one time, this seems a little inefficient. 目前只有一个线程可以同时使用循环队列,这似乎效率很低。

class CircularQueue<T> implements Iterable<T>{
  private T queue[];
  private int head, tail, size;
  @SuppressWarnings("unchecked")
  public CircularQueue(){
     queue = (T[])new Object[20];
     head = 0; tail = 0; size = 0;
  }
  @SuppressWarnings("unchecked")
  public CircularQueue(int n){ //assume n >=0
     queue = (T[])new Object[n];
     size = 0; head = 0; tail = 0;
  }
  public synchronized boolean join(T x){
    if(size < queue.length){
        queue[tail] = x;
        tail = (tail+1)%queue.length;
        size++;
        return true;
     }
     else return false; 
  }
  public synchronized T top(){
    if(size > 0)
        return queue[head];
    else
        return null;
  }
  public synchronized boolean leave(){
    if(size == 0) return false;
    else{
        head = (head+1)%queue.length;
        size--;
        return true;
    }
  }
  public synchronized boolean full(){return (size == queue.length);}
  public boolean empty(){return (size == 0);}

  public Iterator<T> iterator(){
      return new QIterator<T>(queue, head, size);
  }
  private static class QIterator<T> implements Iterator<T>{
      private T[] d; private int index; 
    private int size; private int returned = 0;
      QIterator(T[] dd, int head, int s){
          d = dd; index = head; size = s;
      }
    public synchronized boolean hasNext(){ return returned < size;}
    public synchronized T next(){
        if(returned == size) throw new NoSuchElementException();
        T item = (T)d[index];
        index = (index+1) % d.length;
        returned++;
        return item;
    }
    public void remove(){}
  }
}

Any advice or help that you can give would be appreciated! 您可以提供的任何建议或帮助将不胜感激!

In addition to missing making your empty() method synchronized, your iterator is not sufficiently insulated from the host queue. 除了缺少使您的empty()方法同步之外,迭代器还无法与主机队列充分隔离。 The problem is not that its methods are synchronized on iterator instances, although it's true that they are. 问题不在于其方法在迭代器实例上是同步的,尽管确实如此。 Your iterator is making copies of the host queue's data, so as to iterate over a snapshot of the queue. 您的迭代器正在复制主机队列的数据,以便遍历队列的快照。 That's a fine idea, and in that case synchronizing on the iterator itself is the right thing to do. 那是个好主意,在这种情况下,在迭代器本身上进行同步是正确的事情。

But you don't implement it fully. 但是您没有完全实现它。 Specifically, it is not sufficient for the constructor to execute d = dd; 具体来说,对于构造函数执行d = dd;是不够的d = dd; . Arrays are objects, so that just sets the iterator's array reference to refer to the same array object that the host queue uses. 数组是对象,因此只需将迭代器的数组引用设置为引用主机队列使用的同一数组对象。 Instead, you need to make a copy of that array. 相反,您需要复制该数组。 There are several ways to do so, but I would prefer to invoke the array's clone() method -- short and sweet. 有几种方法可以做到这一点,但是我更喜欢调用数组的clone()方法-简短而甜蜜。

Even then, there are thread safety issues that synchronization of your classes' methods alone cannot defend against. 即使这样,仍然存在线程安全问题,仅靠类的方法同步是无法防御的。 Some of these involve consistency of the object over multiple method invocations. 其中一些涉及对象在多个方法调用上的一致性。 For example, suppose one thread enqueues an object on an instance of your queue. 例如,假设一个线程将一个对象排入队列实例中。 If that queue is shared among threads, then the one that enqueued the object cannot safely assume that it can dequeue an object later, or if it does dequeue one, that it will be the same one that it enqueued. 如果该队列在线程之间共享,则使该对象排队的队列不能安全地假定它可以稍后使一个对象出队列,或者如果确实使一个队列出队列,则该对象与被排队的对象相同。 If it wants to be able to make such assumptions then it must either provide more broadly scoped protection or ensure that the queue instance it uses is not shared. 如果它希望能够做出这样的假设,则它必须提供范围更广的保护,或者确保它使用的队列实例不被共享。

Other issues revolve around mutation of the enqueued objects, if indeed they are mutable. 其他问题围绕着排队对象的突变,即使它们确实是可变的。 Their state is not protected by synchronization of the queue and its iterator. 它们的状态不受队列及其迭代器同步的保护。

empty()未同步,迭代器方法上的已同步保护了迭代器(可能没有用),但保护了队列本身。

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

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