Golang Go语言中 ioutil.Discard 这个 io.Writer 是线程安全的吗

null
Golang Go语言中 ioutil.Discard 这个 io.Writer 是线程安全的吗

19 回复

文档没写就看源码呗

ioutil.Discard 对象本身没有保存什么信息,进去的东西都被丢弃了

更多关于Golang Go语言中 ioutil.Discard 这个 io.Writer 是线程安全的吗的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


丢弃的数据需要什么线程安全?

😳 假设楼主 writer 并发写的话,最终顺序是啥?

https://golang.org/src/io/ioutil/ioutil.go

从 122 行开始看,
type devNull int
var Discard io.Writer = devNull(0)

没有 data,何来 data race ?

受教

就是 /dev/null


1. 没有 data 也可以有 race,data race 是 race condition 的子集
2. 这个事要从 144 行来看,ioutil.Discard 被专门做成了线程安全的
3. ioutil.Discard 曾经不是线程安全的,还被当案例写下来了。https://blog.golang.org/race-detector

在多线程并发上除了 data race 还有什么 race ?或者说软件开发上,还有别的导致不线程安全的 race?


文件的 close 和 open 之间可以有 race,这个和常见的 data race 是两回事

Node.js 里,如果写
console.log(‘exit’)
process.exit()
前面的写操作是异步的,所以这两行之间有 race

串行执行的时候,你 close 掉文件再写入一样有问题,这已经不是 race 了,是 data dependency。


不是先 close 再 read 的问题
是 close 和 open 的问题
我指的是 https://github.com/golang/go/issues/7970

你举的先 close 再 open 例子就是典型的 data race

感谢,非常感谢


1. 我不知道你说的“典型的 data race ”是什么。
https://blog.regehr.org/archives/490 明确地给出了 data race 和 race condition 的定义和它们之前的关系
2. 我上面说 “ data race 是 race condition 的子集”,这是错的,这两个东西互相不是对方的子集
3. 按照我发的链接里的定义,不同线程上的 2 个 open 和 close 之间构不成 data race,因为只有 open 一个地方用到了内存地址



f.fd = -1 没有 happens-before close(fd),所以才引发了这个问题,在 Java Language Specification 里,这种因为 order 引发的错误,不管是代码写错还是编译器重排序引起,都称为 data race。

也有只把 data race 定义为 memory access 引发问题的,比如你给的那个博客。



https://docs.oracle.com/javase/specs/jls/se9/html/jls-17.html#jls-17.4.5
When a program contains two conflicting accesses (§17.4.1) that are not ordered by a happens-before relationship, it is said to contain a data race.

https://docs.oracle.com/javase/specs/jls/se9/html/jls-17.html#jls-17.4.1
Two accesses to (reads of or writes to) the same variable are said to be conflicting if at least one of the accesses is a write.

Java Language Specification 也把 data race 定义为 memory access

难道说这个 f.fd 不是共享的 instance field?

Table 17.4-B. Surprising results caused by statement reordering - valid compiler transformation

重排序引发的问题也当成 data race 的案例解释了

#17 这里的重排 是值 CPU 乱序指令 执行吗?

在Golang(Go语言)中,ioutil.Discard 是一个 io.Writer 接口的实现,它实现了 Write 方法,但不做任何实际的写入操作,即所有数据都被丢弃。关于 ioutil.Discard 是否线程安全的问题,我们可以从以下几个方面进行分析:

  1. 内部实现ioutil.Discard 实际上是一个 io.Writer 的简单封装,指向一个空的结构体或零值。其 Write 方法直接返回 (len(p), nil),其中 p 是传入的字节切片。这个过程不涉及任何共享状态的修改,因此是天然的线程安全的。

  2. 并发访问:由于 ioutil.DiscardWrite 方法不依赖于任何外部状态或资源,多个goroutine同时调用 Write 方法时,不会产生数据竞争或状态不一致的问题。

  3. 官方文档与保证:虽然官方文档没有明确声明 ioutil.Discard 是线程安全的,但从其实现逻辑可以推断出它是线程安全的。在Go语言中,无状态或状态不可变的操作通常被认为是线程安全的。

综上所述,ioutil.Discard 在Go语言中是线程安全的。它可以在多个goroutine之间安全地共享和使用,而无需担心数据竞争或并发问题。如果你需要在并发环境中丢弃数据而不进行任何实际写入,ioutil.Discard 是一个非常好的选择。

回到顶部