
在并发编程中,同步是防止数据竞争并确保线程或 goroutine 以协调方式运行的关键。 想象一下,您在协调多个生产者和消费者访问共享资源(例如缓冲区或队列)时遇到问题。这种经典的并发挑战被称为生产者-消费者问题。在这种情况下,同步对于确保生产者不会覆盖数据以及消费者不会读取无效或陈旧的数据至关重要。同步是必要的,因为如果没有正确的同步,同时访问共享数据可能会导致竞争条件、数据损坏或崩溃。如果缓冲区已满,生产者需要等待,如果缓冲区为空,消费者需要等待。 在某些情况下您有一个固定大小的有界缓冲区,并且您需要管理多个生产者和消费者之间对其的访问。
什么是sync.cond?
缓冲区(或队列),其大小固定。多个生产者生成项目并将其添加到缓冲区,而多个消费者则从中删除项目。挑战是:
package main
import (
"fmt"
"sync"
"time"
)
const buffersize = 5
type buffer struct {
data []int
mu sync.mutex
cond *sync.cond
}
func (b *buffer) produce(item int) {
// producer logic to add item to the buffer
}
func (b *buffer) consume() int {
// consumer logic to remove item from the buffer
return 0
}
func main() {
buffer := &buffer{data: make([]int, 0, buffersize)}
buffer.cond = sync.newcond(&buffer.mu)
var wg sync.waitgroup
// start producer goroutines
for i := 1; i <= 3; i++ {
wg.add(1)
go func(id int) {
defer wg.done()
for j := 0; j < 5; j++ { // each producer creates 5 items
buffer.produce(id*10 + j) // produce unique items based on id and j
time.sleep(100 * time.millisecond)
}
}(i)
}
// start consumer goroutines
for i := 1; i <= 3; i++ {
wg.add(1)
go func(id int) {
defer wg.done()
for j := 0; j < 5; j++ { // each consumer consumes 5 items
item := buffer.consume()
fmt.printf("consumer %d consumed item %d\n", id, item)
time.sleep(150 * time.millisecond)
}
}(i)
}
wg.wait()
fmt.println("all producers and consumers finished.")
}
在示例中使用sync.cond
初始化:
buffer.cond = sync.newcond(&buffer.mu)
生产者方法(生产):
func (b *buffer) produce(item int) {
b.mu.lock()
defer b.mu.unlock()
// wait if the buffer is full
for len(b.data) == buffersize {
b.cond.wait() // release lock and wait until signaled
}
// add item to the buffer
b.data = append(b.data, item)
fmt.printf("produced item %d\n", item)
// signal a consumer that an item is available
b.cond.signal()
}
消费方法(消费):
func (b *Buffer) consume() int {
b.mu.Lock()
defer b.mu.Unlock()
// Wait if the buffer is empty
for len(b.data) == 0 {
b.cond.Wait() // Release lock and wait until signaled
}
// Remove item from the buffer
item := b.data[0]
b.data = b.data[1:]
fmt.Printf("Consumed item %d\n", item)
// Signal a producer that space is available
b.cond.Signal()
return item
}
想象一下您的任务多个 goroutine 需要等待特定条件才能继续,例如:
以上就是理解Go中的syncCond:生产者-消费者场景中的Goroutine同步的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号