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

Java 如何使循环队列完全线程安全,java,concurrency,thread-safety,synchronized,java-threads,Java,Concurrency,Thread Safety,Synchronized,Java Threads,目前,我刚刚将synchronized添加到了大多数方法中,因为如果没有synchronized,这些方法将不会是线程安全的。我还需要实现什么来确保它是线程安全的 还有,有没有更好的办法。目前,一次只能有一个线程使用循环队列,这似乎有点低效 class CircularQueue<T> implements Iterable<T>{ private T queue[]; private int head, tail, size; @SuppressWarnin

目前,我刚刚将synchronized添加到了大多数方法中,因为如果没有synchronized,这些方法将不会是线程安全的。我还需要实现什么来确保它是线程安全的

还有,有没有更好的办法。目前,一次只能有一个线程使用循环队列,这似乎有点低效

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(){}
  }
}
类循环队列实现了Iterable{
专用T队列[];
头、尾、大小;
@抑制警告(“未选中”)
公共循环队列(){
队列=(T[])新对象[20];
头部=0;尾部=0;尺寸=0;
}
@抑制警告(“未选中”)
公共循环队列(int n){//假设n>=0
队列=(T[])新对象[n];
大小=0;头部=0;尾部=0;
}
公共同步布尔联接(TX){
if(大小<队列长度){
队列[tail]=x;
tail=(tail+1)%queue.length;
大小++;
返回true;
}
否则返回false;
}
公共同步T top(){
如果(大小>0)
返回队列[头];
其他的
返回null;
}
公共布尔休假(){
如果(size==0)返回false;
否则{
head=(head+1)%queue.length;
大小--;
返回true;
}
}
public synchronized boolean full(){return(size==queue.length);}
public boolean empty(){return(size==0);}
公共迭代器迭代器(){
返回新的队列(队列、头、大小);
}
私有静态类QIterator实现迭代器{
私有T[]d;私有int索引;
private int size;返回的private int=0;
起动器(T[]dd,内部头部,内部s){
d=dd;指数=head;尺寸=s;
}
公共同步布尔hasNext(){return返回

如果您能提供任何建议或帮助,我们将不胜感激

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

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

除了缺少同步
empty()
方法之外,迭代器与主机队列的隔离度不够。问题不是它的方法在迭代器实例上是同步的,尽管它们确实是同步的。迭代器正在复制主机队列的数据,以便在队列的快照上进行迭代。这是一个好主意,在这种情况下,在迭代器上进行同步是正确的做法

但你没有完全实现它。具体来说,构造函数执行
d=dd是不够的。数组是对象,因此只需将迭代器的数组引用设置为引用主机队列使用的相同数组对象。相反,您需要创建该数组的副本。有几种方法可以做到这一点,但我更愿意调用数组的
clone()
方法——又短又甜

即使如此,仍然存在线程安全问题,单靠类方法的同步无法抵御这些问题。其中一些涉及对象在多个方法调用上的一致性。例如,假设一个线程将队列实例上的对象排队。如果该队列在线程之间共享,那么让对象排队的线程就不能安全地假定它以后可以让一个对象排队,或者如果它确实让一个对象排队,那么它将是它排队的同一个对象。如果它希望能够做出这样的假设,那么它必须提供范围更广的保护,或者确保它使用的队列实例不被共享


其他问题围绕排队对象的变异,若它们确实是可变的。它们的状态不受队列及其迭代器的同步保护。

除了缺少同步
empty()
方法之外,迭代器与主机队列的隔离度不够。问题不是它的方法在迭代器实例上是同步的,尽管它们确实是同步的。迭代器正在复制主机队列的数据,以便在队列的快照上进行迭代。这是一个好主意,在这种情况下,在迭代器上进行同步是正确的做法

但你没有完全实现它。具体来说,构造函数执行
d=dd是不够的。数组是对象,因此只需将迭代器的数组引用设置为引用主机队列使用的相同数组对象。相反,您需要创建该数组的副本。有几种方法可以做到这一点,但我更愿意调用数组的
clone()
方法——又短又甜

即使如此,仍然存在线程安全问题,单靠类方法的同步无法抵御这些问题。其中一些涉及对象在多个方法调用上的一致性。例如,假设一个线程将队列实例上的对象排队。如果该队列在线程之间共享,那么让对象排队的线程就不能安全地假定它以后可以让一个对象排队,或者如果它确实让一个对象排队,那么它将是它排队的同一个对象。如果它希望能够做出这样的假设,那么它必须提供范围更广的保护,或者确保它使用的队列实例不被共享


其他问题围绕排队对象的变异,若它们确实是可变的。它们的状态不受队列及其迭代器同步的保护。

要保护队列不受迭代器的影响,克隆