2010-01-11 33 views
12

Tengo varios hilos (algunos creados por Process X, otros por Process Y, y otros), y cada hilo debe escribirse en un archivo MyFile. Sin embargo, si Thread T1 empieza a escribir a MyFile primero, y luego, cuando Thread T2 empieza a escribir, tiene que esperar a que T1 a versión del archivo, para que se pueda leer el contenido que fueron escritos en Thread T1. En otras palabras, cada hilo tendría un método finalizeThread, así:Bloqueo de archivos Java

private void finalizeThread() { 
    File f = new File("MyFile.dat"); 
    f.createNewFile(); // atomically creates the file, if it doesn't exist 
    locked_section { 
     readContentsFromFile(f); // read contents if some other thread already modified the file 
     modifyContentsFromFile(f); // modify 
     writeFile(f); // write, so that new threads can see the content modified by this thread 
    } 
} 

Mi pregunta es: ¿Cómo puedo lograr que la locked_section en el código anterior? Estaba buscando en la clase FileLock, pero dice en el Javadoc que "Los bloqueos de archivos se llevan a cabo en nombre de toda la máquina virtual Java. No son adecuados para controlar el acceso a un archivo por varios subprocesos dentro de la misma máquina virtual"..

+0

¿Estás seguro de que realmente quieres el método finalize()? – Dmitry

+0

No, el nombre del método no es en realidad 'finalize'. Es un método/devolución de llamada que se llama después de que el hilo (en realidad, un conjunto de hilos, pero esto es irrelevante para el caso) ha terminado con su trabajo, ya que no estoy usando los hilos de la API Java Concurrency API estándar. Voy a cambiarle el nombre para evitar confusiones con 'Object # finalize'. –

Respuesta

12

Si solo se accede al archivo desde su programa, el objeto de bloqueo sincronizado está bien. Pero si desea proteger el archivo para que no sea modificado por otros programas mientras está trabajando en él, puede usar las funciones de bloqueo de archivos de Java en java.nio.channels.FileLock (example). Como dice el texto, tenga en cuenta que, en algunos sistemas operativos, los programas aún pueden cambiar archivos si no comprueban si hay un bloqueo de archivos existente.

+0

Gracias por los comentarios. Sí, mi programa solo accede a él, y cada hilo verificará/comprobará la existencia de un bloqueo antes de proceder. El problema es que la API que estoy utilizando puede engendrar hilos de varios procesos diferentes, y algunos hilos del mismo proceso, y me temo que puede haber problemas asociados con eso, ya que el 'javadoc' FileLock lo menciona. –

+0

Tal vez estoy malinterpretando algo, pero ¿qué quiere decir que tiene hilos generados por diferentes procesos? Un proceso tiene su propio espacio de direcciones, y cualquier subproceso que cree comparte ese espacio de direcciones. ¿Tienes múltiples procesos cada uno generando múltiples hilos que pueden intentar escribir en el mismo archivo? –

+2

El Javadoc dice: "Los bloqueos de archivos se llevan a cabo en nombre de toda la máquina virtual Java.No son adecuados para controlar el acceso a un archivo por varios hilos dentro de la misma máquina virtual. Los objetos de bloqueo de archivos son seguros para su uso por múltiples hilos concurrentes. " ¿No son las dos últimas oraciones mutuamente excluyentes? Creo que alguien tendrá que echar un vistazo al código fuente ... En el siguiente párrafo dice "Esta API de bloqueo de archivos está destinada a mapearse directamente a la facilidad de bloqueo nativo del sistema operativo subyacente." Por lo tanto * debe * funcionar como flock (Linux) o LockFileEx (Windows). – AndiDog

0

Te querrás sincronizar en algún objeto. Por ejemplo:

synchronized(fileLockObject) { 
    readContentsFromFile(f); 
    modifyContentsFromFile(f); 
    writeFile(f); 
} 
+1

Hola Anon., Gracias por tu comentario. Sin embargo, no puedo hacer eso, ya que estos hilos son generados por diferentes procesos, y no puedo compartir ese objeto entre todos los hilos, de ahí la necesidad de otro enfoque. Estos tampoco son subprocesos estándar de '' concurrencia. * 'De Java, sino hilos creados por una API de Oracle. –

+0

Si son procesos diferentes (y por lo tanto máquinas virtuales separadas), puede simplemente usar la clase 'FileLock'. –

+0

Sí, pero algunos son generados por el mismo proceso. Pero sí, tal vez una estrategia híbrida funcionaría. Gracias. –

2

En lugar de compartir un bloqueo, tal vez podría tener un proceso separado que era responsable de mantener un bloqueo en el archivo. Para comenzar su paso de lectura/modificación/escritura, un Tema debería solicitar este proceso central para el bloqueo a través de HTTP, o mensajes, o lo que quiera. Si se deniega la solicitud, el subproceso se irá a dormir, se despertará e intentará de nuevo. De lo contrario, el hilo leería/modificaría/escribiría y luego le diría al proceso de bloqueo que está liberando el bloqueo.

+1

Si va a utilizar un proceso central, es probable que este proceso maneje la lectura/escritura, por lo que no tiene que preocuparse por lo que sucede cuando un hilo muere después de que se le haya emitido el bloqueo (bueno, sí, pero es menos complicado). – wds