Java IO 流中的同步方法

在Java中,从Java 1.0开始类就有方法java.io.InputStream

public synchronized void mark(int readlimit) {}

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

为什么这两种方法同步,而其他所有方法都不同步?


答案 1

有一些相互矛盾的事实表明,同步关键字在这里只是一个错误:

  1. 当然,这只是对开发人员的提示。方法为空,关键字不在子类中继承。synchronized

  2. 另一方面,其他方法不同步,甚至是抽象和空方法。这意味着我们被警告不要忘记标记/重置时的同步,但我们没有被警告并发调用。这没有意义,因为没有同步,并发读取将无法工作。read()

  3. 许多 JDK 流实现对同步关键字的使用不连贯。

  4. java.io.InputStream与相反,几乎没有有用的基本方法实现,但被制成了一个类。因此,它试图在这种“骨架提供”和声明通用方法契约之间取得平衡。java.nio.Buffer


答案 2

这是因为 mark() 和 reset() 协同工作的原因,如文档中所示。

公共无效标记(int readlimit):标记此输入流中的当前位置。对该方法的后续调用将此流重新定位在最后标记的位置,以便后续读取重新读取相同的字节。reset

如果您有多个线程共享相同的 InputStream,如果这两种方法无法同步,则可能会导致问题。

更新到评论

java.io.InputStream是一个抽象类,所以我认为同步的更适合继承 InputStream 作为提示的类。方法 和 将仅在返回 true 时使用。并在类中返回 false。mark()reset()markSupported()java.io.InputStream#markSupported()

/**
 * 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;
}

推荐