goroutine 锁机制

go的锁: https://www.infoq.com/presentations/go-locks/

  • 直接用一个flag为啥不行?
    • 不是原子性的 not atomic
    • reordering 指令重排序
  • hardware可以实现
    • x86: XCHG
    • LOCK prefix 很好使(一切的基础)
      • LOCK ADD
      • LOCK CMPXCHG
  • 一步一步地实现,改进
    • 最基础的实现,利用上面的指令CAS,spinslock,循环检测。问题:死循环检测导致CPU浪费
    • 改进:futex
      • flag int: 0: unlocked; 1:locked; 2: there's a waiter
      • 逻辑:自旋失败的时候,线程可以去睡觉,等到flag修改的时候再醒来
        • 读方法:
          • 死循环
            • if (atomic.cas(&flag, 0, 1))
              • 获得锁 ,干活
            • CAS失败了, 设置flag为sleeping
            • atomic.xchg(&flag, 2)
            • futex(&flag, FUTEX_WAIT, 2) 这样kernal就是put当前线程sleep,当别的线程调用FUTEX_WAKE的时候叫醒我。
        • 写方法:
          • 死循环
            • if(atomic.cas(&flag,0,1))
              • 干活
              • 将flag设置为unlocked: v := atomic.Xchg(&flag, 0)
              • 如果有人在等,那就叫醒他:
              • if v == 2
                • futex(&flag, FUTEX_WAKE, ...)
      • interface:futex syscall
      • mechanism:kernal-managed queue
      • kernal怎么实现futex的?
        • 哈希表,链表法解决冲突。利用用户空间的内存地址做哈希,找到一个bucket,放置我们要suspend的线程
        • 挂起线程
      • cost
        • 无竞争(单线程)~13ns,cost of user-space atomic CAS = ~13ns
        • 有竞争(12cpu)0.9us,900ns,cost of user-space atomic CAS + syscall + thread context switch = ~0.9us
    • 所以是sleep好还是spin好?
      • 如果获取锁的时间短,那就spin好了
      • 如果长,那就挂起
    • 那就混合起来吧:hybrid
      • 先自旋几次,自旋几次获取不到了,那就调用futex syscall。
      • 这个操作在go里面有,在java的锁升级过程也是这样。
    • go在user-space搞的,能不能做得更好?
      • 由于整个go都是运行在线程里的,切换goroutine只需10ns,线程切换需要a us
        • we can block the goroutine without bloking the underlying thread
          • to avoid the thread context switch cost
        • go来实现goroutine切换,调度(scheduling)
      • 这就是 go semaphore
        • 与futex很类似,不过用的是sleep/wake goroutine
    • 还有啥问题
      • 被唤醒的goroutine很可能被在CAS竞争中输掉:there's a delay between when the flag was set to 0 and this goroutine was rescheduled
      • 解决:sync.Mutex
        • 实际上在等待队列中,还是需要lock:each hash bucket needs a lock:it's a futex
        • sync.Mutex
          • uses a semaphore
            • uses futexes(per hash bucket)锁住每个hash表里的bucket来实现高并发的同步问题
              • uses spin-locks(futex也是用的哈希表,他也要处理哈希表冲突问题)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值