常用的线程锁
常用的锁
互斥锁(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)乐观锁虽然去除了加锁解锁的操作,但是一旦发生冲突,重试的成本非常高,所以只有在冲突概率非常低,且加锁成本非常高的场景时,才考虑使用乐观锁。
?
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!