介绍一下几种典型的锁?

读写锁
  • 多个读者可以同时进行读
  • 写者必须互斥(只允许一个写者写,也不能读者写者同时进行)
  • 写者优先于读者(一旦有写者,则后续读者必须等待,唤醒时优先考虑写者)
互斥锁

一次只能一个线程拥有互斥锁,其他线程只有等待

互斥锁是在抢锁失败的情况下主动放弃CPU进入睡眠状态直到锁的状态改变时再唤醒,而操作系统负责线程调度,为了实现锁的状态发生改变时唤醒阻塞的线程或者进程,需要把锁交给操作系统管理,所以互斥锁在加锁操作时涉及上下文的切换。互斥锁实际的效率还是可以让人接受的,加锁的时间大概100ns左右,而实际上互斥锁的一种可能的实现是先自旋一段时间,当自旋的时间超过阀值之后再将线程投入睡眠中,因此在并发运算中使用互斥锁(每次占用锁的时间很短)的效果可能不亚于使用自旋锁

条件变量

互斥锁一个明显的缺点是他只有两种状态:锁定和非锁定。而条件变量通过允许线程阻塞和等待另一个线程发送信号的方法弥补了互斥锁的不足,他常和互斥锁一起使用,以免出现竞态条件。当条件不满足时,线程往往解开相应的互斥锁并阻塞线程然后等待条件发生变化。一旦其他的某个线程改变了条件变量,他将通知相应的条件变量唤醒一个或多个正被此条件变量阻塞的线程。总的来说互斥锁是线程间互斥的机制,条件变量则是同步机制。

自旋锁

如果进线程无法取得锁,进线程不会立刻放弃CPU时间片,而是一直循环尝试获取锁,直到获取为止。如果别的线程长时期占有锁,那么自旋就是在浪费CPU做无用功,但是自旋锁一般应用于加锁时间很短的场景,这个时候效率比较高。

发表评论

后才能评论

评论(3)

  • 文峯 普通 2022-06-17 11:50 下午

    自旋锁可以用于以下情况:锁被持有的时间短,而且线程并不希望在重新调度上花费太多的成本。

  • 文峯 普通 2022-05-07 9:41 下午

    根据实现的不同,读写锁可以分为「读优先锁」和「写优先锁」

  • -.- 普通 2021-11-11 11:25 上午

    帅地,询问一个问题,我的程序的锁卡死了,但是我gdb attach上去后,发现只有一个线程在LOCK_WAIT,然后退出gdb,发现这个线程又正常了,这是什么情况?
    PS:我在另外的一个线程又进行一个lock,sleep,unlock的操作,这个是否会对锁产生影响,日志中看到已经unlock了。