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:
arrayOriginal dan arraySrc adalah sama apabila dimulakan, manakala arrayDist adalah semua sifar.
Mulakan urutan untuk menjalankan kaedah copy() untuk menyalin arraySrc ke arrayDist.
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.
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.
System.arraycopy
ialah kaedahnative
:Tiada sambungan yang diperlukan antara kaedah
native
dan keselamatan benang, dan saya melihat dokumentasiSystem.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:Kendalian khusus bagi contoh ini ialah:
arrayOriginal dan arraySrc adalah sama apabila dimulakan, manakala arrayDist adalah semua sifar.
Mulakan urutan untuk menjalankan kaedah
copy()
untuk menyalin arraySrc ke arrayDist.melaksanakan operasi
modify()
dalam utas utama dan mengubah suai kandungan arraySrc Untuk memastikan operasicopy()
mendahului operasimodify()
, saya menggunakan Condition dan menangguhkannya selama dua milisaat. memastikan bahawa salinan dilaksanakan Operasi (iaitu System.arraycopy) mendahului operasi pengubahsuaian.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:
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