ホームページ  >  に質問  >  本文

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

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

巴扎黑巴扎黑2712日前762

全員に返信(3)返信します

  • 高洛峰

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

    System.arraycopyネイティブ メソッドです: 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 的内容. 为了确保 copy() 操作先于 modify() 操作, 我使用 Condition, 并且延时了两毫秒, 以此来保证执行拷贝操作(即System.arraycopy) 先于修改操作.

    4. 根据第三点, 如果 System.arraycopy 是线程安全的, 那么先执行拷贝操作, 再执行修改操作时, 不会影响复制结果, 因此 arrayOriginal 必然等于 arrayDist; 而如果 System.arraycopy线程不安全的 リーリー

      native メソッドとスレッド セーフの間には必要な関係はありません。また、System.arraycopy のドキュメントにはスレッド セーフであるとは記載されていないことがわかりました。 スレッド安全でないことがわかります。
    しかし、System.arraycopy が本当にスレッドアンセーフかどうかを検証するために、小さな例を書きました:
    リーリー

    この例の具体的な操作は次のとおりです:

    <オル>
  • arrayOriginal と arraySrc は初期化時には同じですが、arrayDist はすべてゼロです。

    🎜
  • 🎜 copy() メソッドを実行して arraySrc を arrayDist にコピーするスレッドを開始します。🎜🎜
  • 🎜modify() オペレーションをメインスレッドで実行して、arraySrc の内容を変更します。これは、copy() オペレーションが modify よりも前に行われるようにするためです。 () 操作には、Condition を使用し、変更操作の前にコピー操作 (つまり、System.arraycopy) が確実に実行されるように、2 ミリ秒遅らせます。🎜🎜
  • 🎜 3 番目の点によると、System.arraycopy がスレッドセーフである場合、最初にコピー操作を実行してから変更操作を実行してもコピー結果には影響しないため、arrayOriginal は等しい必要がありますSystem.arraycopythread-unsafe の場合、arrayOriginal は arrayDist.🎜🎜 と等しくありません。 🎜 🎜 🎜上記の推論に基づいて、プログラムを実行すると、次の出力が得られます:🎜 リーリー 🎜最初の 2 回はうまくいきましたが、3 回目はうまくいかなかったことがわかります。🎜

    返事
    0
  • ringa_lee

    ringa_lee2017-04-18 10:25:09

    ネイティブメソッドはヒープ内のメモリを直接コピーします

    返事
    0
  • 怪我咯

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

    もちろん違います。ロックまたは相互排他的である必要があります

    返事
    0
  • キャンセル返事