81 votes

Synchronisation et System.out.println

Si plusieurs threads Système d'appel.out.println(String) sans effectuer de synchronisation, la sortie d'obtenir entrelacés? L' API ne fait aucune mention de la synchronisation, de sorte que cela semble possible, ou est entrelacé de sortie empêché par la mise en mémoire tampon et/ou de la VM modèle de mémoire, etc.?

EDIT:

Par exemple, si chaque thread contient:

System.out.println("ABC");

est la sortie garantis:

ABC
ABC

ou pourrait-il être:

AABC
BC

76voto

maerics Points 47743

Depuis la documentation de l'API ne fait aucune mention de la sécurité des threads sur l' System.out objet , ni ne l' PrintStream#println(String) méthode vous ne pouvez pas supposer que c'est thread-safe.

Cependant, il est tout à fait possible que le sous-jacent de la mise en œuvre de la JVM utilise un thread-safe fonction de l' println méthode (par exemple, printf sur la glibc), de sorte que, en réalité, la sortie sera garanti par votre premier exemple (toujours ABC\n alors ABC\n, jamais entrecoupées de caractères par votre deuxième exemple).

Si vous devez absolument s'assurer qu'aucun println appels intercaler comme vous le décrivez, alors vous devez appliquer exclusion mutuelle manuellement, par exemple:

public void safePrintln(String s) {
  synchronized (System.out) {
    System.out.println(s);
  }
}

Bien sûr, cela aura un considérable impact négatif sur les performances de votre application, ainsi que de compliquer l'utilisation de l'API.

27voto

zzhang Points 549

Le code source OpenJDK répond à votre question:

 public void println(String x) {
    synchronized (this) {
        print(x);
        newLine();
    }
}
 

Référence: http://hg.openjdk.java.net/jdk6/jdk6/jdk/file/39e8fe7a0af1/src/share/classes/java/io/PrintStream.java

15voto

John Vint Points 19804

Tant que vous ne modifiez pas la OutputStream via le Système.sera il est thread-safe.

Si elle est thread-safe, vous pouvez avoir de nombreux threads écrit au Système.tels que

Thread-1
  System.out.println("A");
  System.out.println("B");
  System.out.println("C");
Thread-2
  System.out.println("1");
  System.out.println("2");
  System.out.println("3");

Peut lire

1
2
A
3
B
C

Parmi d'autres combinaisons.

Donc, pour répondre à votre question.

Lorsque vous écrivez à Systme.- il acquiert un verrou sur la OutputStream exemple - il va alors écrire dans le tampon et rincer immédiatement.

Une fois qu'il libère le verrou de la OutputStream est vidé et écrite. Il n'y aurait pas un cas où vous auriez des différentes chaînes rejoint comme 1A 2B

Edit:

Pour répondre à votre édition - Qui ne serait pas le cas avec le Système.out.println. Depuis le PrintStream synchronise l'ensemble de la fonction qu'il va remplir la mémoire tampon, puis le rincer atomiquement. Tout nouveau thread à venir en auront désormais un tampon frais pour travailler avec.

3voto

parkovski Points 1044

Juste pour clarifier, disons que vous avez deux threads, un qui imprime "ABC" et un autre qui imprime "DEF" . Vous n'obtiendrez jamais une sortie comme celle-ci: ADBECF , mais vous pourriez obtenir soit

 ABC
DEF 
 

ou

 DEF
ABC
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X