这里需要挥发性吗?

时间:2012-01-19 15:40:01

标签: java arrays synchronization volatile primitive

在下面的hypotetical场景中,出于更好地理解语言的愿望, int [] 引用需要volatile吗?

public final class SO {

    private int[] ar = new int[10];  // is volatile needed here?
    private int idx = 0;

    public synchronized int get( int i ) {
        return ar[i];
    }

    public synchronized void append( final int val ) {
        if ( idx == ar.length ) {
            // array is too small, let's grow it
            final int[] prev = ar;
            ar = new int[ar.length+ar.length*20/100]
            System.arrayCopy(prev, 0, ar, 0, prev.length);
        }
        ar[idx++] = val;
    }

}

检索 int 的唯一方法是通过 synchronized 方法和修改 int [] 的唯一方法(包括创建一个new int [] )也是通过同步方法完成的。

我不需要添加任何其他同步吗?

4 个答案:

答案 0 :(得分:3)

不,volatile不需要,因为它只在同步方法中访问,所以它已经是线程安全的。您的代码不需要进一步的线程安全。

答案 1 :(得分:2)

它会像你说的那样,因为int受类锁保护 - 但它会慢,因为写和读访问相互阻塞。 (以更快的方式参见CopyOnWriteList实现)

答案 2 :(得分:1)

你很好,除非你的值在没有同步的情况下访问其他地方。

顺便说一下,如果您确实使用ar volatile而不是使用同步方法,则还需要使idx变为易变。但是仍然没有足够的同步,因为同时运行append的两个不同线程可能会造成严重破坏。

实际上,使用volatile数组还有另一个问题:更改数组中的值不会触发缓存同步。只重新分配数组(就像创建更大的数组时一样)会触发缓存刷新。

答案 3 :(得分:1)

根据 java lang specfication  使用volatile为线程添加严格的规则(从主内存读/写),使用synchronized稍微放松一下。