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

huangapple go评论84阅读模式
英文:

How can we use channels in Go in place of mutex?

问题

通道结合通信和同步,保证两个计算(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()
}
英文:

Channels combine communication—the exchange of a value—with synchronization—guaranteeing that two calculations (goroutines) are in a known state.

How is it possible to use the channels in Google Go to perform the functionality of mutex?

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()
}

答案1

得分: 29

使用通道作为互斥锁的示例:

package main

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

func thread1(){
    <-c // 获取票据
    global = 1
    c <- 1 // 归还票据
}

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

func main() {
   c <- 1 // 将初始值放入通道
   go thread1()
   go thread2()
}

您还可以使用chan struct{}而不是chan int来减小内存大小。放入通道的值是struct{}{}(类型为struct{}且内容为空)。请参见Ivan black的评论中的示例。

英文:

An example of using a Channel as a Mutex:

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()
}

You could also use chan struct{} instead of chan int to reduce the memory size. The value that goes into it is struct{}{} (type struct{} and an empty content {}). See Ivan black's comment for an example.

答案2

得分: 5

如果你有一个用1个项目初始化的通道c,那么你可以通过从通道中删除值(<-c)来“检出”“互斥锁”。你可以通过将值添加回去(c <- 1)来“释放”它。

由于从通道中提取操作符a)是原子的,并且b)在有东西可提取之前会阻塞,它可以作为互斥锁使用,因为如果一个执行线程已经检出了它,通道中将没有任何东西,因此它将阻塞,直到已经检出的线程将一个值返回到通道中以供另一个线程提取。

英文:

If you have a channel c that you initialize with 1 item in it, then you can "check out" the "mutex" by removing the value from the channel (&lt;-c). You can "release" it by adding the value back (c &lt;- 1).

Since the extract-from-channel operator a) is atomic, and b) blocks until there's something to extract, it works as a mutex, since if one thread of execution already has it checked out, there will be nothing in the channel, and thus it will block until the thread that had it checked out returns a value to the channel for another thread to extract.

huangapple
  • 本文由 发表于 2010年10月17日 12:39:09
  • 转载请务必保留本文链接:https://go.coder-hub.com/3952061.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定