recherche

Maison  >  Questions et réponses  >  le corps du texte

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

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

巴扎黑巴扎黑2767 Il y a quelques jours801

répondre à tous(3)je répondrai

  • 高洛峰

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

    System.arraycopy est une méthode native :

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

    Il n'y a pas de lien nécessaire entre la méthode native et la sécurité des threads, et j'ai vu que la documentation de System.arraycopy ne mentionnait pas qu'elle était thread-safe, nous pouvons donc savoir que c'est 线程不安全的.

    Mais afin de vérifier si System.arraycopy est vraiment thread-unsafe, j'ai écrit un petit exemple :

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

    Le fonctionnement spécifique de cet exemple est :

    1. arrayOriginal et arraySrc sont identiques une fois initialisés, tandis que arrayDist est entièrement composé de zéros.

    2. Démarrez un fil de discussion pour exécuter la méthode copy() pour copier arraySrc dans arrayDist.

    3. exécute l'opération modify() dans le thread principal et modifie le contenu de arraySrc Afin de m'assurer que l'opération copy() précède l'opération modify(), j'utilise Condition et je la retarde de deux millisecondes. assurez-vous que la copie est exécutée (c'est-à-dire System.arraycopy) avant l'opération de modification.

    4. Selon le troisième point, si System.arraycopy est thread-safe, alors effectuer d'abord l'opération de copie, puis effectuer l'opération de modification n'affectera pas le résultat de la copie, donc arrayOriginal doit être égal à arrayDist et if ; System.arraycopy est 线程不安全的, alors arrayOriginal n'est pas égal à arrayDist.


    Sur la base du raisonnement ci-dessus, exécutez le programme et obtenez le résultat suivant :

    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)

    Comme vous pouvez le constater, cela a bien fonctionné les deux premières fois, mais pas la troisième fois.

    répondre
    0
  • ringa_lee

    ringa_lee2017-04-18 10:25:09

    La méthode native copie directement la mémoire dans le tas

    répondre
    0
  • 怪我咯

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

    Bien sûr que non.

    à verrouiller ou à exclure mutuellement

    répondre
    0
  • Annulerrépondre