java中System.arraycopy是线程安全的吗?
巴扎黑
巴扎黑 2017-04-18 10:23:09
0
3
795

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

巴扎黑
巴扎黑

membalas semua(3)
小葫芦

System.arraycopy ialah kaedah native:

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

Tiada sambungan yang diperlukan antara kaedah native dan keselamatan benang, dan saya melihat dokumentasi System.arraycopy tidak menyebut bahawa ia selamat untuk benang, jadi kita boleh tahu bahawa ia 线程不安全的.

Tetapi untuk mengesahkan sama ada System.arraycopy benar-benar tidak selamat benang, saya menulis contoh kecil:

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();
    }
}

Kendalian khusus bagi contoh ini ialah:

  1. arrayOriginal dan arraySrc adalah sama apabila dimulakan, manakala arrayDist adalah semua sifar.

  2. Mulakan urutan untuk menjalankan kaedah copy() untuk menyalin arraySrc ke arrayDist.

  3. melaksanakan operasi modify() dalam utas utama dan mengubah suai kandungan arraySrc Untuk memastikan operasi copy() mendahului operasi modify(), saya menggunakan Condition dan menangguhkannya selama dua milisaat. memastikan bahawa salinan dilaksanakan Operasi (iaitu System.arraycopy) mendahului operasi pengubahsuaian.

  4. Menurut titik ketiga, jika System.arraycopy selamat untuk benang, maka melakukan operasi salin dahulu dan kemudian melakukan operasi pengubahsuaian tidak akan menjejaskan hasil salinan, jadi arrayOriginal mestilah sama dengan arrayDist; System.arraycopy ialah 线程不安全的, maka arrayOriginal tidak sama dengan arrayDist.


Berdasarkan alasan di atas, jalankan program dan dapatkan output berikut:

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)

Seperti yang anda lihat, ia berfungsi dengan baik pada dua kali pertama, tetapi bukan kali ketiga.

左手右手慢动作

Kaedah asli menyalin terus memori dalam timbunan

刘奇

Sudah tentu tidak.

untuk dikunci atau saling eksklusif
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan
Tentang kita Penafian Sitemap
Laman web PHP Cina:Latihan PHP dalam talian kebajikan awam,Bantu pelajar PHP berkembang dengan cepat!