2012-06-17 2 views
7

Учитывая следующее:Является ли PrintWriter потокобезопасным?

public class CConsole { 
    public static PrintWriter pw = new PrintWriter(System.out, true); 
} 

Является ли CConsole.pw.format("%d %d", x, y) потокобезопасной? То есть, если несколько потоков используют этот вызов и где он описывается как потокобезопасный. Я не вижу его в описании класса PrintWriter и в описании метода format().

+0

[Этот ответ] (http://stackoverflow.com/a/714424/1079354) может пролить свет на него. – Makoto

+1

Возможный дубликат [Является ли поток PrintWriter сокета Java безопасным?] (Http://stackoverflow.com/questions/714287/is-a-java-sockets-printwriter-thread-safe) –

+0

Я действительно видел это. Это не совсем тот же вопрос, и никаких данных нет. – H2ONaCl

ответ

8

Этот вопрос не имеет однозначный ответ ...

Writer, что суперкласс PrintWriter явно упоминает в своей конструкторской документации, что все критические секции синхронизации либо на самом Writer, например, или с явной заданного объекта.Следовательно, Writer явно потокобезопасен ...

К сожалению, документация подкласса PrintWriter не дает никаких явных выражений. Он наследует объект блокировки , но нет способа узнать, все ли дополнительные или переопределенные методы по-прежнему являются потокобезопасными.

С другой стороны, насколько я могу судить, Sun/OpenJDK PrintWriter implementation содержит synchronized блоков практически в каждом методе. Но, похоже, это явно не документированное поведение.

Я предпочел бы не рискуйте и предположим, что PrintWriter не поточно-, чем полагаться на незарегистрированной поведение и сожалеть об этом в долгосрочной перспективе ...

0

Нет, на самом деле это не потокобезопасно.

Смотрите запись() methonds в PrintWriter.java here

Они пишут синхронизированные на замке (определяется here. - который является объектом Writer Если были синхронизированы на этом это было бы поточно-но в данном случае это не так.

+0

Что вы подразумеваете под потоковой безопасностью? что это связано с тем, что такое блокировка? – Amareswar

5

Поскольку OP не понимает (или, возможно, не верит) ответы на связанный вопрос, я их пересчитать.

  • Основная спецификация (т.е. java docs) не указывают, является ли класс потокобезопасным.

  • Из чтения исходного кода видно, что он является потокобезопасным в том смысле, что все соответствующие операции правильно синхронизированы.

  • Маловероятно, что Oracle намеренно изменит реализацию, чтобы сделать ее небезопасной ... в смысле выше.

  • Однако существуют потребительные случаи, когда PrintWriter не будет полностью потокобезопасной:

    • Если один PrinterWriter используется несколькими потоками, то результат может быть непредсказуемым чередованием выхода из потоки; например если они используют печать, а не println.

    • Если у вас есть несколько PrintWriter сек на одной и той же основной поток, могут возникнуть проблемы из-за PrintWriter сек внутреннего использования BufferedWriter и из-за проблем с блокировкой.

В целом, в настоящее время PrintWriter реализации (в Oracle/OpenJDK кодового) потокобезопасно, но вам все равно нужно быть осторожными в некоторых ситуациях, и есть также возможность других реализаций не может быть потокобезопасным.


Обратите внимание, что цитата, @KazekageGaara найденное из текста книги O'Reilly - «Java Основные классы Справочник» Марк Гранд и Джонатан Кнудсен. Поскольку это не официальная публикация Sun/Oracle, она не является окончательной.

1

Взятые из here, в котором линия говорит:

Все методы PrintWriter, которые многократно записывают в основной поток вывода, обрабатывают внутреннюю синхронизацию, поэтому объекты PrintWriter являются потокобезопасными.

+0

Неработающая ссылка ... –

+0

Происхождение этой цитаты - «Справочник основных принципов Java» Марк Гранд и Джонатан Кнудсен. Это учебник OReilly, а не официальная публикация Sun/Oracle. Эрго, он не является окончательным. –

1
{ 
public void print(Object obj) 
    { 

     write(String.valueOf(obj)); 
    } 

    /* Methods that do terminate lines */ 

} 

печать не синхронизирован ...

Так что, если вы используете метод печати, напишите ур собственный "My Writer" и синхронизировать его.

Или Else

если вы используете Println() .... Тогда синхронизированный ..

{ 

     public void println(Object x) { 
     String s = String.valueOf(x); 
     synchronized (lock) { 
      print(s); 
      println(); 
     } 
    } 

} 
1

Да, это потокобезопасное. Я не понимаю, почему некоторые люди говорят, что это не потокобезопасно. Он определенно имеет элемент «lock», и его методы полностью синхронизируются под этим объектом блокировки.

Некоторые говорят, что метод PrintWriter.print не является потокобезопасным, но это неправильно. PrintWriter.print вызывает write(), который определенно потокобезопасен. Мы все знаем, что метод записи синхронизируется под «блокировкой». Таким образом, метод печати неявно/естественно потокобезопасен.

PrintWriter.println должен быть синхронизирован сам по себе, поскольку он вызывает print() и println(), , оба из которых являются «независимо» потокобезопасными.