欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 财经 > 金融 > Go语言多线程问题

Go语言多线程问题

2025/10/14 2:15:33 来源:https://blog.csdn.net/weixin_52242569/article/details/148513753  浏览:    关键词:Go语言多线程问题

打印零与奇偶数(leetcode 1116)

方法1:使用互斥锁和条件变量

package mainimport ("fmt""sync"
)type ZeroEvenOdd struct {n         intzeroMutex sync.MutexevenMutex sync.MutexoddMutex  sync.Mutexcurrent   int
}func NewZeroEvenOdd(n int) *ZeroEvenOdd {z := &ZeroEvenOdd{n: n}z.evenMutex.Lock()z.oddMutex.Lock()return z
}func (z *ZeroEvenOdd) Zero(printNumber func(int)) {for i := 0; i < z.n; i++ {z.zeroMutex.Lock()printNumber(0)z.current++if z.current%2 == 1 {z.oddMutex.Unlock()} else {z.evenMutex.Unlock()}}
}func (z *ZeroEvenOdd) Even(printNumber func(int)) {for i := 2; i <= z.n; i += 2 {z.evenMutex.Lock()printNumber(i)z.zeroMutex.Unlock()}
}func (z *ZeroEvenOdd) Odd(printNumber func(int)) {for i := 1; i <= z.n; i += 2 {z.oddMutex.Lock()printNumber(i)z.zeroMutex.Unlock()}
}func main() {n := 5zeo := NewZeroEvenOdd(n)var wg sync.WaitGroupwg.Add(3)printFunc := func(x int) {fmt.Print(x)}go func() {defer wg.Done()zeo.Zero(printFunc)}()go func() {defer wg.Done()zeo.Even(printFunc)}()go func() {defer wg.Done()zeo.Odd(printFunc)}()wg.Wait()fmt.Println()
}

方法2:使用通道同步

package mainimport ("fmt""sync"
)type ZeroEvenOdd struct {n       intzeroCh  chan struct{}evenCh  chan struct{}oddCh   chan struct{}done    chan struct{}
}func NewZeroEvenOdd(n int) *ZeroEvenOdd {z := &ZeroEvenOdd{n:      n,zeroCh: make(chan struct{}),evenCh: make(chan struct{}),oddCh:  make(chan struct{}),done:   make(chan struct{}),}close(z.zeroCh) // 初始允许zero执行return z
}func (z *ZeroEvenOdd) Zero(printNumber func(int)) {for i := 0; i < z.n; i++ {<-z.zeroChprintNumber(0)if i%2 == 0 {z.oddCh <- struct{}{}} else {z.evenCh <- struct{}{}}}close(z.done)
}func (z *ZeroEvenOdd) Even(printNumber func(int)) {for i := 2; i <= z.n; i += 2 {<-z.evenChprintNumber(i)z.zeroCh <- struct{}{}}
}func (z *ZeroEvenOdd) Odd(printNumber func(int)) {for i := 1; i <= z.n; i += 2 {<-z.oddChprintNumber(i)z.zeroCh <- struct{}{}}
}func main() {n := 5zeo := NewZeroEvenOdd(n)var wg sync.WaitGroupwg.Add(3)printFunc := func(x int) {fmt.Print(x)}go func() {defer wg.Done()zeo.Zero(printFunc)}()go func() {defer wg.Done()zeo.Even(printFunc)}()go func() {defer wg.Done()zeo.Odd(printFunc)}()wg.Wait()fmt.Println()
}

方法3:使用原子计数器

package mainimport ("fmt""sync""sync/atomic"
)type ZeroEvenOdd struct {n       intcurrent int32cond    *sync.Cond
}func NewZeroEvenOdd(n int) *ZeroEvenOdd {return &ZeroEvenOdd{n:       n,current: 0,cond:    sync.NewCond(&sync.Mutex{}),}
}func (z *ZeroEvenOdd) Zero(printNumber func(int)) {for i := 0; i < z.n; i++ {z.cond.L.Lock()for atomic.LoadInt32(&z.current) != 0 {z.cond.Wait()}printNumber(0)atomic.StoreInt32(&z.current, int32(i+1))z.cond.Broadcast()z.cond.L.Unlock()}
}func (z *ZeroEvenOdd) Even(printNumber func(int)) {for i := 2; i <= z.n; i += 2 {z.cond.L.Lock()for atomic.LoadInt32(&z.current) != int32(i) {z.cond.Wait()}printNumber(i)atomic.StoreInt32(&z.current, 0)z.cond.Broadcast()z.cond.L.Unlock()}
}func (z *ZeroEvenOdd) Odd(printNumber func(int)) {for i := 1; i <= z.n; i += 2 {z.cond.L.Lock()for atomic.LoadInt32(&z.current) != int32(i) {z.cond.Wait()}printNumber(i)atomic.StoreInt32(&z.current, 0)z.cond.Broadcast()z.cond.L.Unlock()}
}func main() {n := 5zeo := NewZeroEvenOdd(n)var wg sync.WaitGroupwg.Add(3)printFunc := func(x int) {fmt.Print(x)}go func() {defer wg.Done()zeo.Zero(printFunc)}()go func() {defer wg.Done()zeo.Even(printFunc)}()go func() {defer wg.Done()zeo.Odd(printFunc)}()wg.Wait()fmt.Println()
}

哲学家进食

package mainimport ("fmt""sync""time"
)const numPhilosophers = 5type Philosopher struct {id          intleftFork    *sync.MutexrightFork   *sync.MutexeatingTimes int
}func (p *Philosopher) think() {fmt.Printf("哲学家 %d 正在思考...\n", p.id)time.Sleep(time.Second * 1)
}func (p *Philosopher) eat() {// 确定拿叉子的顺序(避免循环等待)first, second := p.leftFork, p.rightForkif p.id%2 == 0 { // 偶数ID哲学家先拿右叉子first, second = p.rightFork, p.leftFork}// 获取叉子first.Lock()second.Lock()// 进餐fmt.Printf("哲学家 %d 开始进餐 (第%d次)\n", p.id, p.eatingTimes+1)time.Sleep(time.Second * 1)p.eatingTimes++// 释放叉子second.Unlock()first.Unlock()
}func (p *Philosopher) dine(sem chan struct{}, wg *sync.WaitGroup) {defer wg.Done()for i := 0; i < 3; i++ { // 每个哲学家吃3次便于观察p.think()// 获取就餐许可sem <- struct{}{}p.eat()<-sem}
}func main() {// 初始化叉子forks := make([]*sync.Mutex, numPhilosophers)for i := range forks {forks[i] = &sync.Mutex{}}// 创建哲学家philosophers := make([]*Philosopher, numPhilosophers)for i := range philosophers {philosophers[i] = &Philosopher{id:        i,leftFork:  forks[i],rightFork: forks[(i+1)%numPhilosophers],}}// 使用信号量限制同时就餐人数(最多允许4人同时尝试拿叉子)sem := make(chan struct{}, numPhilosophers-1)var wg sync.WaitGroup// 开始就餐for _, p := range philosophers {wg.Add(1)go p.dine(sem, &wg)}wg.Wait()// 统计每位哲学家就餐次数for _, p := range philosophers {fmt.Printf("哲学家 %d 总共进餐 %d 次\n", p.id, p.eatingTimes)}
}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词