Après que certains googres sérieux, j'ai découvert que la classe RandomAccessFile n'est pas de sécurité. Maintenant, je pourrais utiliser un sémaphore pour verrouiller toutes les lectures et écrires mais je ne pense pas très bien cela. En théorie, il devrait être possible de faire plusieurs lectures et une écriture à la fois. Comment puis-je faire cela en Java? Est-ce possible du tout? P>
merci! p>
5 Réponses :
Je pourrais utiliser un sémaphore pour verrouiller tout lit et écrit mais je ne pense pas cela fonctionne très bien. P> blockQuote>
En ce qui concerne la performance, ne pensez jamais. Toujours mesurer. P>
qui dit,
java.util.concurrent.lock.reentrantreadritelock code> est ce que vous recherchez. P>
Oui, mais je ferai ensuite 2 lectures simultanées ou plus, aléatoireAccessfile ne gérera pas cela. Voir: bugs.sun.com/bugdatabase/view_bug.do?bug_id=4193259 < / a> (la partie "évaluation")
Alors, vous ne pouvez donc pas utiliser un verrou de lecture afin que vous puissiez également utiliser la synchronisation.
Le verrouillage partiel d'un fichier est une entreprise complexe qui, beaucoup de systèmes d'exploitation, évitez de faire. Toutefois, si vous insistez sur le faire, une solution est de concevoir votre propre objet de mécanisme de verrouillage qui enregistre les parties du fichier sont verrouillées. Essentiellement avant de lire ou d'écrire un objet doit demander une serrure pour une plage d'octets spécifique du fichier. Les verrous sont considérés comme des affrontements s'ils se chevauchent du tout dans la plage d'octets. Les serrures de lecture et d'écriture sont traitées différemment: une lecture peut se chevaucher avec n'importe quel nombre de serrures de lecture en toute sécurité, mais une serrure d'écriture doit se chevaucher sans autre serrure, lire ou écrire. Il y a beaucoup de questions sur l'attente ou l'abandon si vous ne pouvez pas obtenir le verrou, et s'il faut bloquer les lectures pendant qu'une écriture attend, mais seulement vous pouvez y répondre de votre application. P>
Compte tenu de la complexité de celle-ci, il peut être préférable de verrouiller le fichier entier. Vérifiez si vous obtenez des performances adéquates - et n'oubliez pas que vous pouvez autoriser plusieurs lectures à la fois, tant qu'il n'y a pas d'écriture. P>
HMMM idée intéressante. J'ai une liste de lecture (INT NR) et un ELIMEDBLOCK (INT NR). Maintenant, je pourrais avoir un sémaphore de tableau [] Serrures = Nouveau sémaphore [10]; Ensuite, dans ReadBlock / Writeblock (), je pourrais faire des verrous [NR% 10] .acquireUnInterruptimativement () Vous ne pouvez penser à aucun problème avec cela. Alough je pense toujours que le fichier aléatoire sous-jacent échouera avec un accès simultané
Le point de faire un objet de verrouillage consiste à empêcher un accès simultané. Vous devez coder pour que tous les threads doivent obtenir une serrure de l'objet de verrouillage avant d'accéder au fichier et la libérer après leur fin.
Considérez cette approche - il permet aux lecteurs illimités et lorsqu'un écrivain veut écrire, il attend que les lecteurs actuels se terminent pour faire son écriture.
class readWriteSemaphore() { private Object lock; List<Thread> readers; Thread writer; readWriteSemaphore() { readers = new LinkedList<Thread>(); // Linked list is inefficient for many threads, FYI writer = null; } /** * Returns true if and only if you have acquired a read * maybe use while(!rws.acquireRead(Thread.currentThread())) Thread.sleep(50); // or something */ boolean acquireRead(Thread t) { synchronized(lock) { if(writer == null) { readers.add(t); return true; } return false; // yes this could go outside the synch block... oh well } } void releaseRead(Thread t) { synchronized(lock) { while(readers.remove(t)); // remove this thread completely } } boolean acquireWrite(Thread t) { synchronized(lock) { if(writer == null) return false; writer = t; } while(readers.size() > 0) Thread.sleep(50); // give readers time to finish. //They can't re-enter yet because we set the writer, // if you attempt to acquire a write, future reads will be false until you're done return true; } void releaseWrite(Thread t) { synchronized(lock) { if(t != writer) throw new IllegalArgumentException("Only writer can release itself"); writer = null; } } }
Ressemble à un java.util.concurrent.lock.reentranTreadreadeAlock? Mais toujours: j'ai besoin d'une façon pour plusieurs lectures et / ou écris pour réussir. Et RandomAccessFile n'autorise pas plusieurs lectures.
Oui, mais randomAccessFile n'autorise pas plusieurs lectures. Je cherche une autre classe le faire.
Si un simple mutex sur l'ensemble du fichier va vous donner un goulot d'étranglement de la performance et Une alternative consiste à mapper le fichier en mémoire sous forme de Je ne serais pas surpris d'entendre que quelqu'un, quelque part a déjà mis en œuvre cela comme une bibliothèque réutilisable. P> randomAccessfile code> n'est pas thread-coffre-fort sans mutex, alors vous devez regarder des alternatives à
RandomAccessFile code>. p>
mappé code> et d'utiliser des tranches du tampon pour permettre à différents threads d'accéder au fichier sans interférer les uns avec les autres. L'écrivain unique / le verrouillage de plusieurs lecteurs multiples à la granularité de l'ensemble serait facile à mettre en œuvre. Vous pouvez également aller plus loin et mettre en œuvre une lecture et une écriture simultanées de sections non chevauchantes du fichier, mais cela serait plus compliqué. P>
java.nio.channel.filechannel code> Est-ce que c'est exactement, c'est-à-dire des lectures simultanées et des écrivies à une seule-filetées. P>
Cela dépend de la façon dont vous lisez et écrivez du fichier, mais la synchronisation des primitives de Java.Util.ConCurrent se produisent très bien sur la JVM moderne.
Je comprends si vous essayez d'utiliser le même fichier randomAccess de différents threads, mais vous devez vraiment faire plusieurs lectures simultanément? Je ne suis pas un expert, mais dans la plupart des cas, le matériel ne sera pas en mesure de servir plusieurs lectures en même temps (je ne sais pas pour les tableaux de disques haut de gamme).
Cela fonctionnera avec des matrices de raid. De plus: lorsque les données proviennent du cache, il peut être récupéré en parallèle.
Si les données proviennent du cache, je pense que l'accès est si rapide (par rapport à l'accès au disque) qui ne fait pas beaucoup de différence. Mais si vous avez vraiment besoin de ce type de parallélisme, je suis curieux de votre contexte. Pouvez-vous donner encore plus de détails?
J'ai une table sur le disque (des centaines de gigaoctets) sur lesquels je ressemble et écrit au hasard. Maintenant, je voudrais avoir un fil séparé qui copie les données.
Si je le lisais correctement (j'ai lu la documentation OpenJDK), le nouveau Asynchronousfilechannel (Java 7) également de le faire: "Les canaux de ce type sont sûrs pour une utilisation par plusieurs threads simultanés".