go条件变量的使用和思考

时间:2025-03-04 08:32:34

源码采用1.9版本;sync包的Cond,条件变量;在我看来,主要是采用他的wait()方法,来控制被阻塞的go程何时去竞争锁;我暂且叫它“双开关控制”(欢迎大神斧正):
废话少说,来个小例子吧:

package main
import (
	"fmt"
	"sync"
	"time"
)

func main() {
	var lc = new()
	//这个locker 为啥传入一个引用?
	var cond = (lc)
	for i := 0; i < 3; i++ {
		go func(x int) {
		   //竞争锁
			()
			//记得要释放锁
			defer ()
			()
			(x)
		}(i)
	}
	//睡眠一会,确保下面的Signal()能通知到一个(难道可能通知不到?)
	(2*)
	()
	()
	(2*)
}

运行结果:

0
2
1

上面例子中有两个问题,我们带着问题,查看Cond的一个重要方法:

func (c *Cond) Wait() {
    //检查cond是否被拷贝
	()
	//将获得锁的那个go程加入等待队列
	t := runtime_notifyListAdd(&)
	//释放锁(可见调用之前要有)
	()
	//go程的等待队列等待唤醒,这个操作是阻塞的,除非本go程被唤醒
	runtime_notifyListWait(&, t)
	//外部记得释放
	()
}

**为啥传入一个引用?**通过wait方法我看到 的操作,如果不是指针变量,也就是发生锁得拷贝,将导致锁不统一,从而发生死锁;
**难道可能通知不到?**如果不等待至少一个go程加入等待队列,此时调用() 通知,是没有作用的;并且我们发现,go程加入等待队列,需要竞争锁,其实我也没有想明白,为啥要加锁,也许是等待队列的操作是线程不安全的。