英文:
If I am using channels properly should I need to use mutexes?
问题
如果我正确使用通道,是否需要使用互斥锁来保护并发访问?
英文:
If I am using channels properly, should I need to use mutexes to protect against concurrent access?
答案1
得分: 12
如果你正确使用通道,就不需要互斥锁。但在某些情况下,使用互斥锁可能更简单。
只需确保在多个 goroutine 尝试访问通道变量之前,正确初始化保存通道值的变量。一旦完成了这一步骤,通过设计,访问通道(例如向其发送值或从中接收值)是安全的。
以下是一些支持文件和引用(强调由我添加):
> 一个单独的通道可以被任意数量的 goroutine 在发送语句、接收操作和对内置函数cap
和len
的调用中使用,无需进一步同步。通道充当先进先出队列。例如,如果一个 goroutine 在通道上发送值,而另一个 goroutine 在接收它们,那么这些值将按发送的顺序接收。
> 在许多环境中,并发编程由于实现对共享变量的正确访问所需的微妙之处而变得困难。Go 鼓励一种不同的方法,即通过通道传递共享值,并且实际上从不由单独的执行线程主动共享。**在任何给定时间,只有一个 goroutine 可以访问该值。通过设计,不会发生数据竞争。**为了鼓励这种思维方式,我们将其简化为一个口号:
>
> 不要通过共享内存来通信;相反,通过通信来共享内存。
>
> 这种方法可能会走得太远。例如,引用计数可能最好通过在整数变量周围放置互斥锁来完成。但作为一种高级方法,使用通道来控制访问使得编写清晰、正确的程序更容易。
这篇文章也非常有帮助:Go 内存模型
此外,引用自sync
包的文档:
> sync 包提供了基本的同步原语,如互斥锁。除了 Once 和 WaitGroup 类型外,大多数原语都是为低级库例程使用而设计的。更好地使用通道和通信来完成更高级别的同步。
英文:
You don't need mutex if you use channels correctly. In some cases a solution with mutex might be simpler though.
Just make sure the variable(s) holding the channel values are properly initialized before multiple goroutines try to access the channel variables. Once this is done, accessing the channels (e.g. sending values to or receiving values from them) is safe by design.
Supporting documents with references (emphases added by me):
> A single channel may be used in send statements, receive operations, and calls to the built-in functions cap
and len
by any number of goroutines without further synchronization. Channels act as first-in-first-out queues. For example, if one goroutine sends values on a channel and a second goroutine receives them, the values are received in the order sent.
Effective Go: Concurrency: Share by communicating
> Concurrent programming in many environments is made difficult by the subtleties required to implement correct access to shared variables. Go encourages a different approach in which shared values are passed around on channels and, in fact, never actively shared by separate threads of execution. Only one goroutine has access to the value at any given time. Data races cannot occur, by design. To encourage this way of thinking we have reduced it to a slogan:
>
> Do not communicate by sharing memory; instead, share memory by communicating.
>
> This approach can be taken too far. Reference counts may be best done by putting a mutex around an integer variable, for instance. But as a high-level approach, using channels to control access makes it easier to write clear, correct programs.
This article is also very helpful: The Go Memory Model
Also quoting from the package doc of sync
:
> Package sync provides basic synchronization primitives such as mutual exclusion locks. Other than the Once and WaitGroup types, most are intended for use by low-level library routines. Higher-level synchronization is better done via channels and communication.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论