I am implementing a very simple synchronized Circular Queue as it follows , a friend of mine says that it's prone to deadlock ! but I don't believe so , 
actually when a thread wants to dequeue (poll) if the queue is empty it has to wait until another thread enqueue (offer) an element and vice versa if the queue is full ,
I am not very good at finding deadlock-prone codes, do you think that it's prone to deadlock too ?
import java.util.ArrayList;
class CircularQueue<T>{
    ArrayList<T> q;
    int front , rear , size;
    public CircularQueue(int size){
        q = new ArrayList<T>();
        for (int i = 0 ; i < size ; i++)
            q.add(null);
        front =  0;
        rear =0;
        this.size = size;
     }
     public void offer(T t) throws InterruptedException{
        synchronized(this){
            if ( (rear + 1) % size == front)
                this.wait();    
        }
        rear = (rear + 1) % size;
        q.set(rear, t);
        this.notify();
     }
     public T poll() throws InterruptedException{
        synchronized(this){
            if (rear == front)
                this.wait();
        }
        front = (front+1) % size;
        T result = q.get(front);
        this.notify();
        return result;
     }
}
 
     
     
     
    