【多线程】 -- 常见的锁策略
常见的锁策略1. 乐观锁 悲观锁2. 轻量级锁 重量级锁3. 自旋锁 挂起等待锁4. 读写锁 普通互斥锁5. 公平锁 非公平锁6. 可重入锁 不可重入锁7. synchronized是什么锁1. 乐观锁 悲观锁乐观锁在执行任务之前预期竞争不激烈那就可以先不加锁等后面真实发生了锁竞争再加锁。类似于上厕所不锁门直到有人打开了门看了它一眼它再锁门。悲观锁在执行任务之前预期竞争非常激烈(会发生锁冲突)必须先加锁再执行任务。类似于无论什么时候上厕所都会立马锁上门。二者关注加锁的态度。2. 轻量级锁 重量级锁轻量级锁加锁的过程比较简单用到的资源比较少典型的就是用户态的一些操作(Java层面就可以加锁)。类似于在厕所门口一直询问你好了没不停的自旋一旦有锁进行释放可以第一时间知道。乐观锁是能不加锁就不加锁消耗的资源少所以说乐观锁是一种轻量级锁。重量级锁加锁的过程比较复杂用到的资源比较多典型的就是内核态的一些操作。类似于在厕所外面等也不去询问一直等着别人通知他。悲观锁是无论任何时候都加锁消耗的资源多所以可以说悲观锁是一种重量级锁。二者关注加锁的过程。3. 自旋锁 挂起等待锁自旋锁不停的检查锁是否被释放一旦有锁被释放可以直接获取到锁资源。优点自旋锁是纯用户态的操作可以第一时间获取到锁。缺点有自旋的次数限制和时间限制通过这个限制可以控制对系统资源的消耗。挂起等待锁一直阻塞等待等待被唤醒。优缺点内核态的操作会生成对应的加锁指令要等待被唤醒在等待的过程中会释放CPU资源。4. 读写锁 普通互斥锁读写锁分为读锁和写锁。读锁读操作的时候加读锁共享锁多个读锁可以共存。写锁写操作的时候加写锁排它锁只允许一个写锁执行任务和其他锁是冲突的。在程序运行的过程中并不是所有的操作的需要修改数据但又希望读数据的时候别的线程不要修改数据读和写不能同时加锁当写操作执行的时候不希望任何线程来读数据写完之后才可以对数据进行读取就可以加写锁。写锁和写锁不能共存写锁和读锁不能共存读锁和读锁可以共存普通互斥锁存在竞争关系只能有一个线程释放了锁之后其他线程才可以来抢。5. 公平锁 非公平锁公平锁先来后到先排队的线程先拿到锁后排队的线程后拿到锁。非公平锁所有线程去抢谁抢到就是谁的。一般情况下大多数都是非公平锁因为实现一个公平锁往往需要消耗更多的资源。6. 可重入锁 不可重入锁可重入锁连续加多次锁不造成死锁。不可重入锁连续加多次锁会造成死锁。7. synchronized是什么锁既是乐观锁也是悲观锁。既是轻量级锁也是重量级锁。既是自旋锁也是挂起等待锁。是互斥锁。是非公平锁。是可重入锁。synchronized在竞争不激烈的时候是自旋锁、轻量级锁、乐观锁。synchronized在竞争激烈的时候是挂起等待锁、重量级锁、悲观锁。