Stavo pensando ai problemi di sincronizzazione dei thread in linguaggi compilati come C ++, rispetto ai problemi di sincronizzazione in linguaggi come Java.
Mi chiedo come un linguaggio JVM come Java non (almeno nella pratica) soffra di coredumps / segfaults / comportamento indefinito quando si verificano condizioni di competizione.
Considera un programma C ++ con 2 thread. Supponiamo che ogni thread condivida un riferimento a un std::vector<int>
. Ogni thread scorre continuamente e chiama std::vector<int>::push_back()
- con la sincronizzazione no , nessun blocco di sorta. In questo scenario, è molto probabile che il programma segusterà immediatamente, almeno su qualsiasi piattaforma / compilatore mainstream. Il motivo è ovvio: se un thread attiva una riallocazione tramite una chiamata a push_back
e l'altro thread finisce per scrivere sul vecchio buffer di memoria libero, è probabile che il programma esegua immediatamente il dump di core. Inoltre, i valori vettoriali interni size
e capacity
potrebbero essere danneggiati, causando tutti i tipi di comportamento non definito e arresto anomalo.
Ma questo non sembra accadere in Java. Dato lo stesso scenario, in cui si hanno due thread, ciascuno con un riferimento ad una struttura di dati non sincronizzata (come ArrayList<Integer>)
, e ogni thread chiama ArrayList<Integer>.add()
, il peggiore che sembra accadere in pratica è che viene lanciata un'eccezione, probabilmente un'eccezione ArrayIndexOutofBounds
- e, naturalmente, l'ordine di inserimento è totalmente casuale.
Mi rendo conto che la JVM sta eseguendo solo il codice byte (tranne quando sta eseguendo il codice JIT), ma alla fine quel codice byte o codice macchina JIT deve interagire con la memoria di sistema effettiva. Presumo che Java controlli automaticamente gli indici di array con ogni accesso e che la semantica del linguaggio e il garbage collector garantiscano che tutti i riferimenti siano non-penzolanti, ma con una struttura di dati non sincronizzata, quando la memoria potrebbe letteralmente essere tirata fuori dai piedi del programma da un altro thread, in qualsiasi momento, in che modo la JVM non esegue il segfault in questo scenario a meno che non sia in qualche modo in grado di sincronizzare le letture / scritture di memoria?