我们如何使用Go中的通道代替互斥锁?

Kev*_*vin 14 go goroutine

通道将通信 - 值的交换 - 与同步相结合 - 保证两个计算(goroutine)处于已知状态.

如何使用Google Go中的频道执行互斥锁功能?

package main

import "sync"

var global int = 0
var m sync.Mutex

func thread1(){
    m.Lock()
    global = 1
    m.Unlock()
}

func thread2(){
    m.Lock()
    global = 2
    m.Unlock()
}

func main(){
   go thread1()
   go thread2()
}
Run Code Online (Sandbox Code Playgroud)

Mar*_*rot 23

将Channel用作互斥锁的示例:

package main

var global int = 0
var c = make(chan int, 1)

func thread1(){
    <-c // Grab the ticket
    global = 1
    c <- 1 // Give it back
}

func thread2(){
    <-c
    global = 2
    c <- 1
}

func main() {
   c <- 1 // Put the initial value into the channel
   go thread1()
   go thread2()
}
Run Code Online (Sandbox Code Playgroud)

您也可以使用chan struct{}而不是chan int减少内存大小.进入它的值是struct{}{}(类型struct{}和空内容{}).有关示例,请参阅Ivan black的评论.

  • 虽然通道为受保护的数据提供了一个很好的解决方案,但对于一个作者和许多读者而言,它是一种效率较低的解决方案 (2认同)

Amb*_*ber 5

如果您有一个c初始化其中包含1个项目的频道,则可以通过删除频道(<-c)中的值来"签出""互斥" .您可以通过添加值back(c <- 1)来"释放"它.

由于来自通道的提取操作符a)是原子的,并且b)阻塞直到有东西被提取,它起到互斥的作用,因为如果一个执行的线程已经检出它,那么通道中就没有任何东西,并且因此它将阻塞,直到检出它的线程将一个值返回到通道以供另一个线程提取.