2014-11-10 9 views
7

Versione corta: Perché non utilizzare il File.createNewFile() per il blocco dei file? O più nello specifico: ci sono problemi se è usato per bloccare una directory dei dati delle applicazioni?Blocco dell'esistenza di file in Java


Dettagli:

Vorrei proteggere la mia applicazioni directory dei dati utilizzando un file di blocco: se il file esiste lock, la directory è bloccata e la chiusura dell'applicazione con un messaggio di errore. Se non esiste verrà creato e l'applicazione continua. All'uscita il file sarà cancellato.

Il blocco non verrà creato spesso (ad esempio, le prestazioni non sono un problema) e non ho alcun problema con l'eliminazione manuale del file di blocco in caso di un errore (ad esempio, non riuscire a eliminare il file non è un problema).

Il codice simile a questa:

File lockFile = new File("lock"); 
boolean lockCreated = lockFile.createNewFile(); 
if (lockCreated) 
{ 
    // do stuff 
    lockFile.delete(); 
} 
else 
{ 
    System.err.println("Lockfile exists => please retry later"); 
    // alternative: Wait and retry e.g. 5 times 
} 

ora sono un po 'confuso circa il Javadoc of createNewFile():

Atomicamente crea un nuovo file vuoto denominato da questo percorso astratto se e solo se un file con questo nome non esiste ancora. Il controllo dell'esistenza del file e la creazione del file se non esiste sono una singola operazione che è atomica rispetto a tutte le altre attività del file system che potrebbero influire sul file.

Nota: questo metodo deve essere non essere utilizzato per il blocco dei file, in quanto il protocollo risultante non può essere eseguito per funzionare in modo affidabile. Si consiglia di utilizzare la funzione FileLock.

Quali sono i potenziali problemi menzionati nella nota, considerando che il controllo dell'esistenza e la creazione del file sono atomici?

This forum post da dicembre 2007 indica "differenze significative di piattaforma" in base al Javadoc di File.delete() (anche se non riesco a trovare una tale dichiarazione da almeno Java SE 1.4.2). Ma anche se ci fossero tali differenze: potrebbero davvero causare il fallimento del blocco (cioè due processi pensano che la directory dei dati sia utilizzabile allo stesso tempo)?


Nota: I Do non vogliono una delle seguenti:

  • Blocco di un file in modo che nessun altro processo può accedere e/o modificarlo (maggior parte delle informazioni che ho trovato sembra discutere di questo problema).
  • Assicurarsi che nessun altro processo possa rimuovere il blocco.
  • Sincronizza più thread della stessa JVM (anche se penso che la mia soluzione dovrebbe essere in grado di gestire anche questo).
+1

dipende da cosa intendono per "atomico". c'è atomic-within-your-own-app e atomic-for-all-apps-on-the-system. Sospetto che sia atomico solo per la tua app, e non posso fare nulla per proteggere altri processi paralleli che saltano dentro e sniping il file da te. –

+2

È possibile eseguire il pagamento su un file e aprire una porta. –

+0

@MarcB: Mi aspettavo che Javadoc significasse atomicità a livello di sistema: "... sono una singola operazione che è atomica rispetto a ** tutte ** altre attività del filesystem_ ...". Ma buon punto, non ci pensare ... – siegi

risposta

1

La risposta breve: il blocco basato su file affidabile in Java non è pratico.

La risposta lunga: il problema del blocco basato su file, in qualsiasi sistema operativo, dipende sempre dal tipo di sistema di archiviazione da cui proviene il file. Quasi tutti i file system di rete (NFS, SAMBA, ecc.) Hanno sincronizzazioni molto inaffidabili (o almeno imprevedibili) su file creati o cancellati che rendono sconsigliabile un approccio generale di Java. In alcuni sistemi operativi, utilizzando i file system locali, a volte è possibile ottenere ciò che desideri. Ma è necessario comprendere il file system sottostante e le sue caratteristiche e procedere con attenzione.

+2

Grazie per la tua risposta! Capisco che i file system di rete si comportano in modo imprevedibile. Per quanto mi riguarda, il Javadoc suona piuttosto rigido. Quindi, Javadoc è corretto ed è garantito che la creazione di check e file sia atomica (almeno per i file system locali) o che non lo sia e che Javadoc sia errato e debba essere riformulato (ad esempio, una base best effort_ ...). Aggiungere una nota piuttosto aspecifica non dovrebbe invalidare le garanzie fatte prima ... – siegi

1

Il Javadoc di Files.createFile(…), parte di java.nio.file disponibile da Java 7, ripete la promessa di atomicità ma non menziona nulla sul blocco basato su file.


Il mio ragionamento:

  • il metodo più recente (da java.nio.file.Files) è influenzato dalle stesse (o simili) problemi come il più vecchio (da java.io.File) e Javadoc è semplicemente mancano queste informazioni ...
  • ... oppure il metodo più recente si comporta in modo più prevedibile e corretto.

Data la gestione degli errori e della specifica in java.nio.file è stata generalmente migliorata rispetto alla classe File (esistente fin JDK 1.2), assumo la seconda alternativa è corretto.


La mia conclusione: l'utilizzo di Files.createFile(…) va bene per questo caso d'uso.