搜尋

首頁  >  問答  >  主體

java中System.arraycopy是线程安全的吗?

请问一下 在java中System.arraycopy是不是线程安全的

巴扎黑巴扎黑2807 天前853

全部回覆(3)我來回復

  • 高洛峰

    高洛峰2017-04-18 10:25:09

    System.arraycopy 是一个 native 方法:

    public static native void arraycopy(Object src,  int  srcPos,
                                        Object dest, int destPos,
                                        int length);

    native 方法和线程安全之间又没有什么必然联系, 并且我看 System.arraycopy 的文档中也没有提到它是线程安全的, 因此就可以知道它是 线程不安全的.

    不過為了驗證 System.arraycopy 是否真的是線程不安全的, 我寫了一個小例子:

    public class ArrayCopyThreadSafe {
        private static int[] arrayOriginal = new int[1024 * 1024 * 10];
        private static int[] arraySrc = new int[1024 * 1024 * 10];
        private static int[] arrayDist = new int[1024 * 1024 * 10];
        private static ReentrantLock lock = new ReentrantLock();
    
        private static void modify() {
            for (int i = 0; i < arraySrc.length; i++) {
                arraySrc[i] = i + 1;
            }
        }
    
        private static void copy() {
            System.arraycopy(arraySrc, 0, arrayDist, 0, arraySrc.length);
        }
    
        private static void init() {
            for (int i = 0; i < arraySrc.length; i++) {
                arrayOriginal[i] = i;
                arraySrc[i] = i;
                arrayDist[i] = 0;
            }
        }
    
        private static void doThreadSafeCheck() throws Exception {
            for (int i = 0; i < 100; i++) {
                System.out.println("run count: " + (i + 1));
                init();
                Condition condition = lock.newCondition();
    
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        lock.lock();
                        condition.signalAll();
                        lock.unlock();
                        copy();
                    }
                }).start();
    
    
                lock.lock();
                // 这里使用 Condition 来保证拷贝线程先已经运行了.
                condition.await();
                lock.unlock();
    
                Thread.sleep(2); // 休眠2毫秒, 确保拷贝操作已经执行了, 才执行修改操作.
                modify();
    
                if (!Arrays.equals(arrayOriginal, arrayDist)) {
                    throw new RuntimeException("System.arraycopy is not thread safe");
                }
            }
        }
    
        public static void main(String[] args) throws Exception {
            doThreadSafeCheck();
        }
    }

    這個範例的具體操作是:

    1. arrayOriginal 和 arraySrc 初始化時是相同的, 而 arrayDist 是全為零的.

    2. 啟動一個執行緒運行 copy() 方法來拷貝 arraySrc 到 arrayDist 中.

    3. 在主線程執行modify() 操作, 修改arraySrc 的內容. 為了確保modify() 操作, 修改 arraySrc 的内容. 为了确保 copy() 操作先于 modify() 操作先於modify() 操作, 我使用Condition, 並且延時了兩毫秒, 以此來保證執行拷貝操作(即System.arraycopy) 先於修改操作.

    4. 根據第三點, 如果System.arraycopy 是线程安全的, 那么先执行拷贝操作, 再执行修改操作时, 不会影响复制结果, 因此 arrayOriginal 必然等于 arrayDist; 而如果 System.arraycopy线程不安全的 是線程安全的, 那麼先執行拷貝操作, 再執行修改操作時, 不會影響複製結果, 因此arrayOriginal 必然等於arrayDist; 而如果

      線程不安全的< /code>, 那麼arrayOriginal 不等於arrayDist.

    根據上面的推理, 運行一下程式, 有如下輸出:

    run count: 1
    run count: 2
    Exception in thread "main" java.lang.RuntimeException: System.arraycopy is not thread safe
        at com.test.ArrayCopyThreadSafe.doThreadSafeCheck(ArrayCopyThreadSafe.java:62)
        at com.test.ArrayCopyThreadSafe.main(ArrayCopyThreadSafe.java:68)

    可以看到, 前兩次運行的好好的, 但是第三次​​就不行了.🎜

    回覆
    0
  • ringa_lee

    ringa_lee2017-04-18 10:25:09

    native方法 直接copy堆中記憶體

    回覆
    0
  • 怪我咯

    怪我咯2017-04-18 10:25:09

    當然不是啦。要加鎖或互斥的

    回覆
    0
  • 取消回覆