4 ms·
I'm not familiar with golang, but I did read about a concern with variable mutability and race conditions when communicating across channels: https://bluxte.net
by yingw787 7y ago
I'm not familiar with golang, but I did read about a concern with variable mutability and race conditions when communicating across channels: https://bluxte.net/musings/2018/04/10/go-good-bad-ugly/#mutability-is-hardcoded-in-the-language https://bluxte.net/musings/2018/04/10/go-good-bad-ugly/#muta...
"""
As we saw above there is no way in Go to have immutable data structures. This means that once we send a pointer on a channel, it's game over: we share mutable data between concurrent processes. Of course a channel of structures (and not pointers) copies the values sent on the channel, but as we saw above, this doesn't deep-copy references, including slices and maps, which are intrinsically mutable. Same goes with struct fields of an interface type: they are pointers, and any mutation method defined by the interface is an open door to race conditions.
So although channels apparently make concurrent programming easy, they don't prevent race conditions on shared data. And the intrinsic mutability of slices and maps makes them even more likely to happen.
"""
Is this still a concern, and if it is, would it be addressed in Go 2?
- blaisio 7y agoThat isn't really the sort of thing Golang is trying to address, at least, not directly. Go is very unlikely to add immutable data structures at this point. And Go is not built to prevent race conditions. There is a race detector that can detect many race conditions in running programs, but nothing in the type system.
- yingw787 7y agoIMHO type systems are pretty much impossible to change after the fact (see: Python's `str` type and the whole 2/3 migration fiasco), which is why I thought to bring it up since it's a major version change. I think a lack of support for efficient immutable types gets in the way of `golang` being a concurrency-first language, if the language endorses CSP with native support for goroutines and channels in the first place. How you can write simple, reliable, and efficient user code (https://golang.org https://golang.org) if using your favored concurrency model results in race conditions?
- apta 7y ago> How you can write simple, reliable, and efficient user code (https://golang.org https://golang.org) if using your favored concurrency model results in race conditions? You can't. And the language is not expressive enough to be able to write generic immutable data structures as you have in Scala/Java/Kotlin/etc.
- Thaxll 7y ago99% of languages don't have race condition prevention and yet they're doing fine. Go has a pretty good race condition detector.
- zeeboo 7y agoIndeed, I believe it's impossible to statically prevent race conditions in a turing complete language. Data races can be prevented, but that's just a subset of all possible race conditions.
- Quekid5 7y agoI think Erlang does? I don't really know Erlang, but AFAIK there's no way to share anything mutable between processes. Any data which is shared is (semantically) copied when it's sent to a different process. (Ignoring FFI, and such.) Same thing applies to the STM "subset" of Haskell -- conformance to which is statically verified by the type checker[1]. [1] There's no particular magic going on wrt. checking -- STM is a monad. It just happens to have "magic" runtime support.
- zeeboo 7y agoThose disallow data races, not race conditions. I find that this blog post explains the distinction well: https://blog.regehr.org/archives/490 https://blog.regehr.org/archives/490
- Quekid5 7y agoAh, yes. My bad... I missed that crucial detail. Still, maybe a non-TC protocol language could fulfill the criteria?
- mytailorisrich 7y agoThe purpose of channels is to provide synchronisation and messaging between goroutines, not to prevent race conditions on shared data. Go also provides mutexes that are more suited for that. Sure, passing a pointer through a channel does not in itself provide any protection to the data it references but such protection is not always required. There's a separation of concerns that allows more flexibility.
- erik_seaberg 7y ago> such protection is not always required Safety should be the default, with a way to opt out for people who have thought really hard about the consequences. If I have to opt into the safe version, I need tooling to complain about everywhere I didn't do so.
- mytailorisrich 7y agoA pointer is neither safe nor unsafe and in my view people should be expected to know what they are doing when passing pointers across concurrent threads of execution. It's not rocket science. Goroutines are supposed to be lightweight so it makes sense to allow lightweight communication.
- qtplatypus 7y agoOn the other hand how often have you read in documentation “Do not mutate this buffer” or the equivalent? It is very possible to create traps for people who pick up your code later on. Having the compiler detect those problems rather then it causing a runtime error is something highly desirable.
- blablabla123 7y ago> This means that once we send a pointer on a channel, it's game over Yes, as long as you keep sharing the references. So just don't reference that stuff you sent across a channel. Usually there is little reason to use pointers in Go anyway [1] except when building methods to mutate the associated type (think: struct). That said, it's fairly easy to build cascaded structures that are automatically deep-copied during assignment by not using pointers. So that's a pretty safe way to go, moreover one should keep in mind that Go doesn't try to be functional in any way, so immutable data is not such a thing there. [1] https://medium.com/@vCabbage/go-are-pointers-a-performance-optimization-a95840d3ef85 https://medium.com/@vCabbage/go-are-pointers-a-performance-o...
- xyzzy_plugh 7y agoUntil you blow out the stack.