Golang如何限制同时执行任务的协程数量
Golang如何限制同时执行任务的协程数量 我正在Coursera上学习Go语言,最后一个练习是实现“哲学家就餐”算法。
- 5位哲学家可以就餐,每位需要吃3次
- 同时只能有2位哲学家就餐
- 共有5根筷子
我想定义一个host函数,用于控制同时只能有2位哲学家就餐。
由于知识有限,我在实现上遇到了困难。
我尝试使用一个通道,并将哲学家发送到通道中,但我仍然不知道/不理解如何限制允许同时就餐的哲学家数量。
非常感谢!
package main
import (
"fmt"
"sync"
"time"
)
type ChopS struct {
sync.Mutex
}
type Philosopher struct {
number int
leftCs, rightCs *ChopS
}
func (p Philosopher) GetNumber() int {
return p.number
}
func (p Philosopher) Eat(wg *sync.WaitGroup) {
for i := 1; i <= 3; i++ {
p.leftCs.Lock()
p.rightCs.Lock()
fmt.Println("starting to eat <", p.number, ">")
fmt.Println("Finishing eating <", p.number, ">")
p.leftCs.Unlock()
p.rightCs.Unlock()
time.Sleep(2 * time.Second)
}
}
func NewPhilospher(number int, leftCs, rightCs *ChopS) Philosopher {
var p Philosopher
p.number = number
p.leftCs = leftCs
p.rightCs = rightCs
return p
}
func createChops() []*ChopS {
CSticks := make([]*ChopS, 5)
for i := 0; i < 5; i++ {
CSticks[i] = new(ChopS)
}
return CSticks
}
func createPhilosophers() []Philosopher {
var philos []Philosopher
CSticks := createChops()
for i := 0; i < 5; i++ {
philos = append(philos, NewPhilospher(i, CSticks[i], CSticks[(i+1)%5]))
}
return philos
}
func host() {
// only 2 Philosophers can eat at the same time
}
func main() {
philos := createPhilosophers()
var wg sync.WaitGroup
for i := 0; i < 5; i++ {
wg.Add(1)
go philos[i].Eat(&wg)
}
wg.Wait()
}
更多关于Golang如何限制同时执行任务的协程数量的实战教程也可以访问 https://www.itying.com/category-94-b0.html
2 回复
更多关于Golang如何限制同时执行任务的协程数量的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
可以使用带缓冲的通道作为信号量来限制并发数量。以下是实现host函数的示例:
func host(philosophers []Philosopher, wg *sync.WaitGroup) {
// 创建缓冲大小为2的通道,限制同时只有2个哲学家可以就餐
semaphore := make(chan struct{}, 2)
for i := 0; i < len(philosophers); i++ {
wg.Add(1)
go func(p Philosopher) {
defer wg.Done()
// 获取许可,如果通道已满则阻塞
semaphore <- struct{}{}
// 哲学家开始就餐
p.Eat()
// 释放许可
<-semaphore
}(philosophers[i])
}
}
修改主函数使用host函数:
func main() {
philos := createPhilosophers()
var wg sync.WaitGroup
host(philos, &wg)
wg.Wait()
}
修改Eat方法去掉WaitGroup参数:
func (p Philosopher) Eat() {
for i := 1; i <= 3; i++ {
p.leftCs.Lock()
p.rightCs.Unlock()
fmt.Println("starting to eat <", p.number, ">")
fmt.Println("Finishing eating <", p.number, ">")
p.leftCs.Unlock()
p.rightCs.Unlock()
time.Sleep(2 * time.Second)
}
}
完整实现示例:
package main
import (
"fmt"
"sync"
"time"
)
type ChopS struct {
sync.Mutex
}
type Philosopher struct {
number int
leftCs, rightCs *ChopS
}
func (p Philosopher) Eat() {
for i := 1; i <= 3; i++ {
p.leftCs.Lock()
p.rightCs.Lock()
fmt.Println("starting to eat <", p.number, ">")
time.Sleep(time.Second)
fmt.Println("Finishing eating <", p.number, ">")
p.leftCs.Unlock()
p.rightCs.Unlock()
time.Sleep(2 * time.Second)
}
}
func NewPhilospher(number int, leftCs, rightCs *ChopS) Philosopher {
return Philosopher{
number: number,
leftCs: leftCs,
rightCs: rightCs,
}
}
func createChops() []*ChopS {
CSticks := make([]*ChopS, 5)
for i := 0; i < 5; i++ {
CSticks[i] = new(ChopS)
}
return CSticks
}
func createPhilosophers() []Philosopher {
var philos []Philosopher
CSticks := createChops()
for i := 0; i < 5; i++ {
philos = append(philos, NewPhilospher(i+1, CSticks[i], CSticks[(i+1)%5]))
}
return philos
}
func host(philosophers []Philosopher, wg *sync.WaitGroup) {
semaphore := make(chan struct{}, 2)
for i := 0; i < len(philosophers); i++ {
wg.Add(1)
go func(p Philosopher) {
defer wg.Done()
semaphore <- struct{}{}
p.Eat()
<-semaphore
}(philosophers[i])
}
}
func main() {
philos := createPhilosophers()
var wg sync.WaitGroup
host(philos, &wg)
wg.Wait()
}
这个实现使用带缓冲的通道作为计数信号量,缓冲大小设置为2确保同时只有两位哲学家可以就餐。当通道已满时,尝试发送的协程会阻塞,直到有哲学家就餐完毕释放许可。

