Golang 中的通道和互斥锁有什么区别?



我听说当程序具有高并发性时,channelsycn.Mutex.Lock()更好。但为什么渠道更有效率呢?在我看来,要实现一个安全的缓冲池(我认为通道可以被视为缓冲池(,必须使用锁。

如果channel更有效,为什么会有sycn.Mutex?因为我可以编写下面的代码来模拟sync.Mutex

type seme struct {
lock chan int
locked bool
}

func (l *seme)Lock() {
// state 0 for initial, 1 for locked, 2 for free.
if atomic.CompareAndSwapInt32(&l.state, 0, 1) {
l.lock = make(chan int, 1)
}
l.lock <- 0
l.state = 1
}
func (l *seme)UnLock() {
if !atomic.CompareAndSwapInt32(&l.state, 1, 2)  {
panic("UnLock a free Lock")
}
l.state = 2
<- l.lock
}

如果channel在任何地方都比mutex好,为什么我要使用mutex?也就是说,我什么时候应该使用mutex而不是channel?有人能给我举个例子吗?

通道与互斥锁有根本不同。

一个有足够细节的正确答案太长了,所以让我们只介绍主要亮点,特别是在Go频道方面:

Go通道在并发例程(goroutines(之间提供类型的数据传输
  • sync.Mutex为并发例程(goroutines(之间的共享内存提供互斥
  • 数据传输表示复制某种类型的值。Goroutine a将一个值放入通道:

    var v T  // v is a value of type T
    ...
    ch <- v  // put v's value into the channel
    

    v放入通道的尝试何时以及是否会发生,以及如果您愿意,可以对此做些什么,都会变得有点复杂,但如果通道是缓冲的,那么至少一些值可以立即进入,而不会有任何阻塞,这样发送goroutine就可以继续。如果通道未缓冲,则发送器阻塞,直到某个接收器goroutine正在积极等待值。(有时这是可取的,有时不是。(

    同时,goroutine B从通道中取出一个值:

    var w T  // w is also a value of type T
    ...
    w <- ch
    

    或者只是:

    w :=<- ch
    

    同样,这何时以及是否会阻碍,你能做什么,什么时候应该做什么,等等,都可能变得复杂;但在简单的情况下,它等待有一个可用的值——让一些goroutine执行ch <- v,或者如果通道被缓冲,则已经执行了——然后它将放入通道的值复制到变量w中。变量v可能已经改变,甚至在这一点上被完全破坏。已安全存储在通道中,现在已从通道中删除并放入变量w中。

    Go通道具有一些附加功能,例如关闭通道的功能,可以防止在通道上进行进一步写入,并向读取操作发出"数据结束"通知。这可以通过单值读取(w, ok <- ch(进行测试,并在for w := range ch循环中进行隐式测试。

    相比之下,sync.Mutex实例只允许您调用LockUnlock。它不包含任何排队的值(就像缓冲通道一样(,甚至没有一个类型(除了sync.Mutex本身(可以防止您意外地将float发送到预期string或其他类型。这个锁的存在允许两个或多个goroutine使用共享内存区域来完成一些事情。

    通道的运行时实现很可能需要某种互斥。这不一定是sync.Mutex本身:任何提供足够互斥的东西都足够了。在您可能正在使用的Go通道实现中,它不是sync.Mutex,而是一个专门的运行时互斥体。(请注意,此链接指向特定的行,该行可能会随着时间的推移而过时。(由于某些通道代码是由编译器本身直接生成的,因此不应假设此处的运行时例程正在使用:您的编译器可能不同。然而,研究这个特定的实现可能会让你对如何使用通道有所启发。

    互斥体通常比通道简单得多。要查看示例,请将上面通道实现中的代码量(不包括编译器的内联插入(与这个特定Go实现的sync.Mutex源代码进行比较。

    Golang中的并发程序有两种通信方式。

    1. sync包:通过共享内存进行通信。

    2. 通道:通过交流共享记忆。

    Go推荐

    不要通过共享内存进行通信。相反,通过共享内存沟通。

    哪些操作是原子操作?互斥锁呢?解决这个问题

    最新更新