dqvrlgi3247 2014-05-17 15:42
浏览 35
已采纳

Golang:避免比赛条件

What are some good practices to prevent race conditions in Go?

The only one I can think of is not sharing data between goroutines - the parent goroutine sends a deep copy of an object rather than the object itself, so the child goroutine can't mutate something that the parent can. This would use up more heap memory, but the other alternative is to learn Haskell :P

Edit: also, is there any scenario in which the method I described above can still run into race conditions?

  • 写回答

2条回答 默认 最新

  • dongshen3352 2014-05-18 01:42
    关注

    Race conditions can certainly still exist even with unshared data structures. Consider the following:

    B asks A for the currentCount
    C asks A for the currentCount
    B sends A (newDataB, currentCount + 1)
    A stores newDataB at location currentCount+1
    C sends A (newDataC, currentCount + 1)
    A stores newDataC at currentCount + 1 (overwriting newDataB; race condition)
    

    This race condition requires private mutable state in A, but no mutable shared data structures and doesn't even require mutable state in B or C. There is nothing B or C can do to prevent this race condition without understanding the contract that A offers.

    Even Haskell can suffer these kinds of race conditions as soon as state enters the equation, and state is very hard to completely eliminate from a real system. Eventually you want your program to interact with reality, and reality is stateful. Wikipedia gives a helpful race condition example in Haskell using STM.

    I agree that good immutable data structures could make things easier (Go doesn't really have them). Mutable copies trade one problem for another. You can't accidentally change someone else's data. On the other hand, you may think that you're changing the real one, when you're actually just changing a copy, leading to a different kind of bug. You have to understand the contract either way.

    But ultimately, Go tends to follow the history of C on concurrency: you make up some ownership rules for your code (like @tux21b offers) and make sure you always follow them, and if you do it perfectly it'll all work great, and if you ever make a mistake, then obviously it's your fault, not the language.

    (Don't get me wrong; I like Go, quite a lot really. And it offers some nice tools to make concurrency easy. It just doesn't offer many language tools to help make concurrency correct. That's up to you. That said, tux21b's answer offers lots of good advice, and the race detector is definitely a powerful tool for reducing race conditions. It's just not part of the language, and it's about testing, not correctness; they're not the same thing.)

    EDIT: To the question about why immutable data structures make things easier, this is the extension of your initial point: creating a contract where multiple parties don't change the same data structure. If the data structure is immutable, then that comes for free…

    Many languages have a rich set of immutable collections and classes. C++ lets you const just about anything. Objective-C has immutable collections with mutable subclasses (which creates a different set of patterns than const). Scala has separate mutable and immutable versions of many collection types, and it is common practice to use the immutable versions exclusively. Declaring immutability in a method signature is an important indication of the contract.

    When you pass a []byte to a goroutine, there is no way to know from the code whether the goroutine intends to modify the slice, nor when you may modify the slice yourself. There a patterns emerging, but they're like C++ object ownership before move semantics; lots of fine approaches, but no way to know which one is in use. It's a critical thing that every program needs to do correctly, yet the language gives you no good tools, and there is no universal pattern used by developers.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 MATLAB怎么通过柱坐标变换画开口是圆形的旋转抛物面?
  • ¥15 寻一个支付宝扫码远程授权登录的软件助手app
  • ¥15 解riccati方程组
  • ¥15 display:none;样式在嵌套结构中的已设置了display样式的元素上不起作用?
  • ¥15 使用rabbitMQ 消息队列作为url源进行多线程爬取时,总有几个url没有处理的问题。
  • ¥15 Ubuntu在安装序列比对软件STAR时出现报错如何解决
  • ¥50 树莓派安卓APK系统签名
  • ¥65 汇编语言除法溢出问题
  • ¥15 Visual Studio问题
  • ¥20 求一个html代码,有偿