开发者社区> 问答> 正文

关于获取互斥锁超时后的处理问题?

Discourse 中用 Redis 实现互斥锁有这么一段:

if current_expire_time && now <= current_expire_time.to_i
  redis.unwatch

  got_lock = false
else
  result =
    redis.multi do
      redis.set key, expire_time.to_s
      redis.expire key, validity
    end

  got_lock = !result.nil?
end

完整代码 distributed_mutex.rb

展开
收起
心有灵_夕 2019-12-25 21:56:30 1357 0
1 条回答
写回答
取消 提交回答
  • 当 A 线程还在执行代码时(但是已经超过超时时间),B 线程发现锁已经超过超时时间,然后 B 设置了新的超时时间并获取了锁(仅仅在 A 线程执行完毕后在 log 中记录一条 warning),这种做法是否合理? 感觉上即使一个线程的执行时间如果超过了超时时间,其他线程也不应该获取到这个锁,而是获取锁失败。 A线程要负责释放锁,否则如果A异常退出那么就是死锁了。如果A在锁过期时间内执行不完,A可以extend锁。

    但是在 Discourse 中的使用方式都是下面这样,所以有点迷惑,这种方式使用的话是不是就不需要 Mutex.new.synchronize 来保证原子性了: DistributedMutex.synchronize借助redis实现了跨进程/机器的锁,Mutex#synchronize实现了本进程起的线程级别的锁。的确可以只用redis实现线程级别的锁,但是毕竟有额外的redis读写操作,不如直接用内置的Mutex#synchronize。

    附:Rails 中,关于多线程方面的知识可以在哪里接触到?是一个或 n 个请求就会对应一个线程,又或者是一个 session 会对应一个线程? Rails用的多线程知识可能并不多,顶多是如何在多线程环境下初始化一个单例。多线程可以看puma或者sidekiq。

    2019-12-25 21:56:53
    赞同 展开评论 打赏
问答排行榜
最热
最新

相关电子书

更多
低代码开发师(初级)实战教程 立即下载
冬季实战营第三期:MySQL数据库进阶实战 立即下载
阿里巴巴DevOps 最佳实践手册 立即下载