为什么 Java 和 Go 都在写之前锁定套接字?

Go internal/poll/fd_unix.go 代码在这里


// Write implements io.Writer.

func (fd *FD) Write(p []byte) (int, error) {

    if err := fd.writeLock(); err != nil {

        return 0, err

    }

    defer fd.writeUnlock()

    ......

}

java代码java.net.SocketOutputStream#socketWrite在这里


 private void socketWrite(byte b[], int off, int len) throws IOException {

        if (len <= 0 || off < 0 || len > b.length - off) {

            if (len == 0) {

                return;

            }

            throw new ArrayIndexOutOfBoundsException("len == " + len

                    + " off == " + off + " buffer length == " + b.length);

        }


        FileDescriptor fd = impl.acquireFD();

        try {

            socketWrite0(fd, b, off, len);

        } catch (SocketException se) {

        ......

我不知道为什么我们需要锁定它。另一个问题是 syscall.Write 等效于 <unistd.h> 用 C 编写吗?


红颜莎娜
浏览 157回答 2
2回答

婷婷同学_

好吧,只回答 Java 部分:既然我们已经在讨论实现细节,为什么要停留在 Java 级别呢?本机方法socketWrite0的 OpenJdk 实现的 C 源代码跨越约 70 行代码,显然不是原子的。它使用mallocand执行分配和释放内存free等操作,并且涉及相当多的非平凡逻辑。在那个时候,它调用的用于实际发送数据的函数是否NET_Send直接转换为每个支持的平台上的系统调用都不再重要了。要点是:实现NET_Send在循环中调用 this -function。因此,无论这是否是单独的线程安全的,如果它被多个线程同时调用,输出将是交错的(最好的情况)。

慕码人2483693

好的,假设没有锁定机制,并且两个并发线程/进程正在向套接字写入一些数据。让我们举一个过于简单的例子。Java 应用程序想要写:“你好!你好吗?”。Go 应用想写:“再见。”这两个应用程序都试图同时写入。您期望的输出是:Hello! How are you?See you later.但是,您很有可能会得到类似的东西。HellSee o! How&nbsp; See you are later.&nbsp;you?每当资源在不同的进程/线程之间共享并且没有适当的锁定机制时。遇到不一致和意外行为的可能性很高。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go