• 步比天下
    2022-01-16
    老师,我想问个低级的问题,什么是临界区啊,不太懂

    作者回复: 临界区其实就是一个代码片段。但这个代码片段中有共享的数据,这些数据不支持多个goroutine的并发访问,只能通过像channel、锁等机制同步各个goroutine的访问。同一时间,只能有一个goroutine访问这段代码,修改或读取这段代码所共享的数据。

    共 5 条评论
    15
  • 罗杰
    2022-01-14
    连续三节课都是需要花费 30 分钟才能阅读完,即使是复习也要超过 20 分钟,这几节的内容真的好充实。

    作者回复: 👍

    共 6 条评论
    11
  • Calvin
    2022-01-15
    思考题: 死锁产生的 4 个必要条件:1) 不可剥夺;2) 请求与保持;3) 循环等待;4) 互斥。 以下模块程序会发生死锁,报 fatal error: all goroutines are asleep - deadlock! func op1(mu1, mu2 *sync.Mutex, wg *sync.WaitGroup) { mu1.Lock() time.Sleep(1 * time.Second) mu2.Lock() println("op1: do something...") mu2.Unlock() mu1.Unlock() wg.Done() } func op2(mu1, mu2 *sync.Mutex, wg *sync.WaitGroup) { mu2.Lock() time.Sleep(2 * time.Second) mu1.Lock() println("op2: do something...") mu1.Unlock() mu2.Unlock() wg.Done() } func TestDeadLock(t *testing.T) { var mu1 sync.Mutex var mu2 sync.Mutex var wg sync.WaitGroup wg.Add(2) go op1(&mu1, &mu2, &wg) go op2(&mu1, &mu2, &wg) wg.Wait() }
    展开

    作者回复: 👍

    共 5 条评论
    10
  • aoe
    2022-01-18
    读到这里,明白了 Go 的并发不是万能的! 1. Go 基于 Tony Hoare 的 CSP 并发模型理论,实现了 Goroutine、channel 等并发原语; 2. 使用低级同步原语(标准库的 sync 包以及 atomic 包提供了低级同步原语:Mutex/RWMutex/Cond 等)的性能可以高出 channel 许多倍 3. 有锁的地方就有江湖,高并发下的性能主要拼的是算法,没有一门语言有压倒性优势

    作者回复: 👍

    
    6
  • Geek_62c21a
    2022-04-25
    老师,有两个问题请教您 1,wg.Done() 是不是在函数开始的地方写成 defer wg.Done() 会好点呢? 2,条件变量 broadcast 的时候,以下两种写法有区别吗? 第一种: groupSignal.L.Lock() ready = true groupSignal.Broadcast() groupSignal.L.Unlock() 第二种: groupSignal.L.Lock() ready = true groupSignal.L.Unlock() groupSignal.Broadcast()

    作者回复: 1. 可以的。 2. 虽然Broadcast的参考文档也提到了:It is allowed but not required for the caller to hold c.L during the call. 对于例子来说两种写法都是ok的。但条件变量的测试条件表达式,比如本例子中的ready最好是始终在lock的保护下的。所以这里我建议用了第一种。否则在复杂的场景下,一旦unlock,条件变量测试表达式 就不受控了。

    
    5
  • Calvin
    2022-01-15
    老师,Go 中没有可重入的锁吗?

    作者回复: 没有。Go团队认为递归锁或可重入锁是一个bad idea,所以不支持。

    共 9 条评论
    5
  • 非梧桐不止
    2022-05-27
    老师,既然共享内存的性能比channel好,为什么Go倡导用通信去共享内存呢?

    作者回复: 多数情况下,对性能没有那么高要求,采用基于csp模型的并发设计是主流。

    共 2 条评论
    4
  • singularity of sp...
    2022-02-06
    老师,请问一下Go在没有volatile的情况下如何保证共享变量在不同Goroutine的可见性?如果可见性不能保证的话,那么CAS的正确性应该也不能保证吧?还是说CAS内部的实现已经保证了可见性呢?

    作者回复: Go中没有volatile。但go给出了自己的memory model,https://go.dev/ref/mem 这个也许能回答你的问题。

    共 2 条评论
    3
  • 文经
    2022-01-21
    白老师,我觉得条件变量的例子完全可以用channel来实现,代码逻辑还会更简单一些。 使用条件变量,跟Mutex一样,是基于性能的考虑吗?

    作者回复: 你的想法没错。但条件变量的性能我还真没有和channel对比过,介绍条件变量只是为了给大家“科普”一下它的存在和适合的场景。说实话,条件变量使用的很少。

    
    3
  • 文经
    2022-01-21
    白老师: “atomic 原子操作可用来同步的范围有比较大限制,只能同步一个整型变量或自定义类型变量。如果我们要对一个复杂的临界区数据进行同步,那么首选的依旧是 sync 包中的原语。” 这里说的整型变量和自定义类型变量,是不是可以理解为一个字长的大小。在64位cpu上就是8个字节。因为CPU通过数据总线,一次从内存中最多只能获取一个字长的信息。所以atomic的限制也是一个字长。

    作者回复: 你说的没错,无论整型变量和自定义类型变量,atomic的操作实质上针对的都是字长长度的指针。但我说的复杂临界区,还有另外一个情况,那就是在锁内部有着对数据的更为复杂的判断与操作,而不仅仅是+n,-n,或cas。

    
    3