常用的线程锁

2023-12-13 05:09:09

常用的锁

互斥锁(Mutex Lock)

用于保护共享资源,一次只允许一个线程访问共享资源,其他线程需要等待锁释放后才能访问。互斥锁是最常见的锁类型,用于避免多个线程同时访问共享资源而导致的数据竞争和不一致性。

读写锁(Read-Write Lock)

允许多个线程同时对共享资源进行读操作,但在有写操作时需要互斥访问。读写锁可以提高并发性能,适用于读操作频繁、写操作较少的场景。

自旋锁(Spin Lock)

当线程尝试获取锁时,如果锁已被其他线程占用,该线程会一直循环(自旋)等待锁释放。自旋锁适用于锁占用时间短暂的场景,避免线程切换带来的开销。

条件变量(Condition Variable)

配合互斥锁使用,用于线程间的条件等待和通知。当某个条件不满足时,线程可以等待条件变量的通知;当条件满足时,线程可以向条件变量发送通知唤醒等待的线程。

信号量(Semaphore)

用于控制对共享资源的访问数量,可以用于实现生产者-消费者问题等场景。

互斥锁和读写锁的相同和不同

相同点

互斥性:互斥锁和写锁都能保证在某一时刻下,只有一个进程可以访问共享资源,从而避免数据竞争和不一致性。

不同点

读写权限:互斥锁只能保证互斥访问,一旦一个线程给共享资源加了互斥锁,其他线程就无法访问;读锁可以允许多个线程同时访问共享资源。

性能:在读写操作较多时互斥锁可能会带来较大的性能开销;相对来说读写锁在这种情况下能够提高并发性能。

自旋锁详解

独占锁,当加锁失败时,持续循环等待

与互斥锁的异同点:

1.都是独占锁

2.互斥锁加锁失败,线程陷入内核态,内核将CPU切换给其他线程

自旋锁加锁失败,CPU在该线程持续循环等待

读写锁详解

工作原理:

  • 线程持有读锁时,可以允许多个线程并发的持有读锁
  • 线程持有写锁时,其他线程的读锁和写锁都被阻塞

读优先锁:

当线程A持有读锁时,线程B想请求写锁被阻塞,线程C可以持续获取读锁,当线程A和C都释放读锁时,线程B才能获取写锁。

写优先锁:

当线程A持有读锁时,线程B想请求写锁被阻塞,线程C想请求读锁也会被阻塞,当线程A释放读锁时线程B可以持有写锁。

公平读写锁:

(1)如果一直有读线程获取读锁,那么写线程将永远获取不到写锁,会造成写线程「饥饿」。同样但是如果一直有写线程获取写锁,读线程也会被「饿死」。

(2)公平读写锁比较简单的一种方式是:用队列把获取锁的线程排队,不管是写线程还是读线程都按照先进先出的原则加锁即可,这样读线程仍然可以并发,也不会出现「饥饿」的现象。

乐观锁和悲观锁

(1)悲观锁做事比较悲观,它认为多线程同时修改共享资源的概率比较高,于是很容易出现冲突,所以访问共享资源前,先要上锁

(2)乐观锁做事比较乐观,它假定冲突的概率很低,它的工作方式是:先修改完共享资源,再验证这段时间内有没有发生冲突,如果没有其他线程在修改资源,那么操作完成,如果发现有其他线程已经修改过这个资源,就放弃本次操作乐观锁全程并没有加锁,所以它也叫无锁编程

(3)如果多线程同时修改共享资源的概率比较低,就可以采用乐观锁。SVN 和 Git 也是用了乐观锁的思想,先让用户编辑代码,然后提交的时候,通过版本号来判断是否产生了冲突,发生了冲突的地方,需要我们自己修改后,再重新提交。

(4)乐观锁虽然去除了加锁解锁的操作,但是一旦发生冲突,重试的成本非常高,所以只有在冲突概率非常低,且加锁成本非常高的场景时,才考虑使用乐观锁。

?

线程锁详解 - 知乎 (zhihu.com)

文章来源:https://blog.csdn.net/Ricardo_XIAOHAO/article/details/134959067
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。