简体   繁体   中英

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

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()未同步,迭代器方法上的已同步保护了迭代器(可能没有用),但保护了队列本身。

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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