为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

Go
红颜莎娜 2022-07-18 17:09:23
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 编写吗?
查看完整描述

2 回答

?
婷婷同学_

TA贡献1844条经验 获得超8个赞

好吧,只回答 Java 部分:

既然我们已经在讨论实现细节,为什么要停留在 Java 级别呢?本机方法socketWrite0的 OpenJdk 实现的 C 源代码跨越约 70 行代码,显然不是原子的。它使用mallocand执行分配和释放内存free等操作,并且涉及相当多的非平凡逻辑。在那个时候,它调用的用于实际发送数据的函数是否NET_Send直接转换为每个支持的平台上的系统调用都不再重要了。

要点是:实现NET_Send在循环中调用 this -function。因此,无论这是否是单独的线程安全的,如果它被多个线程同时调用,输出将是交错的(最好的情况)。


查看完整回答
反对 回复 2022-07-18
?
慕码人2483693

TA贡献1860条经验 获得超9个赞

好的,假设没有锁定机制,并且两个并发线程/进程正在向套接字写入一些数据。让我们举一个过于简单的例子。


Java 应用程序想要写:“你好!你好吗?”。


Go 应用想写:“再见。”


这两个应用程序都试图同时写入。


您期望的输出是:


Hello! How are you?

See you later.

但是,您很有可能会得到类似的东西。


HellSee o! How  See you are later.

 you?

每当资源在不同的进程/线程之间共享并且没有适当的锁定机制时。遇到不一致和意外行为的可能性很高。


查看完整回答
反对 回复 2022-07-18
  • 2 回答
  • 0 关注
  • 156 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号