2015-11-04 5 views
25

В Java, начиная с Java 1.0 в классе java.io.InputStream есть методыСинхронизированные методы в Java IO потоков

public synchronized void mark(int readlimit) {} 

и

public synchronized void reset() throws IOException { 
    throw new IOException("mark/reset not supported"); 
} 

Почему эти два метода синхронизированы, а все остальные нет?

+2

Существует нет практической причины для их синхронизации, возможно, это всего лишь подсказка для авторов подкласса InputStream. Кроме того, очень сложно представить реалистичный сценарий, когда обмен потоком между двумя или более потоками будет полезен вообще. (На самом деле трудно представить себе сценарий, где это не приведет к катастрофе.) – biziclop

+0

@biziclop, я придерживаюсь того же мнения. Это похоже на ошибку или рудимент. Я просто хочу услышать другие мнения. Благодаря! – Antonio

+0

Ух, теперь я посмотрел исходный код ... Ненужная синхронизация не так плоха, как тот факт, что базовая реализация 'read (byte [], int, int)' swallows 'IOException's ... – Holger

ответ

6

Есть несколько противоречивых фактов указывает, что синхронизируется ключевое слово просто ошибка здесь:

  1. Наверняка это просто подсказка для разработчиков. Методы пустые, а ключевое слово synchronized не наследуется в подклассах.

  2. С другой стороны, другие методы не синхронизированы, даже абстрактные и пустые методы. Это означает, что нас предупреждали не забывать о синхронизации на отметке/сбросе, но мы не были предупреждены о одновременных вызовах read(). Это не имеет смысла, потому что одновременное чтение не будет работать без синхронизации.

  3. Многие реализации потока JDK имеют некогерентное использование синхронизированных ключевых слов.

  4. java.io.InputStream, поставленный напротив java.nio.Buffer, практически не имеет полезных базовых методов реализации, но был сделан классом. Поэтому он пытается балансировать между этим «скелетным обеспечением» и объявлением контрактов общего метода.

0

Это связано с тем, что метки() и reset() работают вместе, как вы можете видеть в документации.

знак общественного недействительными (интермедиат readlimit): Отмечает текущую позицию в этом входном потоке. Последующий вызов метода reset репозиционирует этот поток с последней помеченной позицией , чтобы последующие чтения перечитывали одни и те же байты.

Если у вас несколько потоков, которые используют один и тот же InputStream, это может привести к проблемам, если эти два метода не будут синхронизированы.

Обновление комментировать

java.io.InputStream является абстрактным классом, так что я думаю, что синхронизированные больше для классов, наследуемых InputStream как намек. Методы mark() и reset() будут использоваться только в том случае, если markSupported() возвращает true. А в классе java.io.InputStream#markSupported() возвращается false.

/** 
* Tests if this input stream supports the <code>mark</code> and 
* <code>reset</code> methods. Whether or not <code>mark</code> and 
* <code>reset</code> are supported is an invariant property of a 
* particular input stream instance. The <code>markSupported</code> method 
* of <code>InputStream</code> returns <code>false</code>. 
* 
* @return <code>true</code> if this stream instance supports the mark 
*   and reset methods; <code>false</code> otherwise. 
* @see  java.io.InputStream#mark(int) 
* @see  java.io.InputStream#reset() 
*/ 
public boolean markSupported() { 
    return false; 
} 
+0

Какая проблема может возникнуть с пустым телом метода? – Antonio

+0

@ Антонио проверить мое обновление :) –

+0

Что касается меня, это похоже на правильный ответ на другой вопрос – Antonio

-1

С меткой() и сброса() методы не имеют никакого кода внутри них, слово «синхронизируется» является только «напоминание» для реализации классов, которые они должны поставить замки или в этих методах, когда они переопределяют их , Это делается для предотвращения условий гонки в многопоточных прецедентах.

Теперь другие методы InputStream не отмечены как «синхронизированные», потому что эти методы никогда не будут генерировать IndexOutOfBoundsException, BufferOverflowException и т. Д. (за исключением случаев, когда вы проходите в плохих размерах буфера). Эти методы всегда возвращают -1, когда больше нет байтов для чтения, а не выбрасывается исключение. Поэтому их не нужно синхронизировать.

Вы заметите, что read() является абстрактным. И реализующие классы задают «синхронизированный», когда они реализуют этот метод.

Другими словами, абстрактный класс InputStream может обрабатывать многопотоки, а также классы реализации.

+0

Второй абзац - полная глупость. Исключения индекса массива не имеют ничего общего с синхронизацией. – EJP

+0

А? В многопоточной среде, когда массивы задействованы так же, как в InputStream, вы можете получить всевозможные исключения, если не вставляете правильные блокировки. –

Смежные вопросы