how can i fix this warning:Non-atomic operation on volatile field 'modCount' :
package org.example;

import java.util.Arrays;
import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.ConcurrentModificationException;

public class CircularArrayDeQueue<E> implements DeQueue<E> {
    private E[] array;
    private int front, rear, size;
    private volatile int modCount;
    private static final int DEFAULT_CAPACITY = 16;

    @SuppressWarnings("unchecked")
    public CircularArrayDeQueue() {
        array = (E[]) new Object[DEFAULT_CAPACITY];
        front = 0;
        rear = 0;
        size = 0;
        modCount = 0;
    }

    public void pushFirst(E elem) {
        expandIfNeeded();
        front = (front - 1 + array.length) % array.length;
        array[front] = elem;
        size++;
        modCount++;
    }

    public void pushLast(E elem) {
        expandIfNeeded();
        array[rear] = elem;
        rear = (rear + 1) % array.length;
        size++;
        modCount++;
    }

    public E popFirst() {
        if (isEmpty()) throw new NoSuchElementException();
        E elem = array[front];
        array[front] = null; // Allow GC to work
        front = (front + 1) % array.length;
        size--;
        modCount++;
        shrinkIfNeeded();
        return elem;
    }

    public E popLast() {
        if (isEmpty()) throw new NoSuchElementException();
        rear = (rear - 1 + array.length) % array.length;
        E elem = array[rear];
        array[rear] = null; // Allow GC to work
        size--;
        modCount++;
        shrinkIfNeeded();
        return elem;
    }

    public E first() {
        if (isEmpty()) throw new NoSuchElementException();
        return array[front];
    }

    public E last() {
        if (isEmpty()) throw new NoSuchElementException();
        return array[(rear - 1 + array.length) % array.length];
    }

    public boolean isEmpty() {
        return size == 0;
    }

    public int size() {
        return size;
    }

    public void clear() {
        Arrays.fill(array, null);
        front = 0;
        rear = 0;
        size = 0;
        modCount++;
    }

    public Iterator<E> iterator() {
        return new DeQueueIterator(front, 1);
    }

    public Iterator<E> descendingIterator() {
        return new DeQueueIterator((rear - 1 + array.length) % array.length, -1);
    }

    private void expandIfNeeded() {
        if (size < array.length) {
            return;
        }
        resize(2 * array.length);
    }

    private void shrinkIfNeeded() {
        if (size * 4 > array.length || array.length <= DEFAULT_CAPACITY) {
            return;
        }
        resize(array.length / 2);
    }

    @SuppressWarnings("unchecked")
    private void resize(int newCapacity) {
        E[] newArray = (E[]) new Object[newCapacity];
        for (int i = 0; i < size; i++) {
            newArray[i] = array[(front + i) % array.length];
        }
        array = newArray;
        front = 0;
        rear = size;
        modCount++;
    }

    private class DeQueueIterator implements Iterator<E> {
        private int current;
        private final int step;
        private final int expectedModCount;

        DeQueueIterator(int start, int step) {
            this.current = start;
            this.step = step;
            this.expectedModCount = modCount;
        }

        public boolean hasNext() {
            return current != rear;
        }

        public E next() {
            if (modCount != expectedModCount) {
                throw new ConcurrentModificationException();
            }
            E item = array[current];
            current = (current + step + array.length) % array.length;
            return item;
        }
    }
}