图解 --乐观锁 悲观锁 可重入锁 独占锁 共享锁 公平锁 非公平锁
1.乐观锁--乐观锁是一种思想,它只解决对共享资源更新时的一致性问题,不解决读取共享资源过程中,其他线程修改了共享资源导致读取的是旧的资源的问题
一般范式为:
private Node enq(final Node node) { for (;;) { Node t = tail; if (t == null) { // Must initialize if (compareAndSetHead(new Node())) tail = head; } else { node.prev = t; if (compareAndSetTail(t, node)) { t.next = node; return t; } } } }
for(;;){ 更新期望共享资源; if(期望共享资源==现实共享资源){ update(); return } }
这种实现存在如下问题1):ABA问题----假如是链表结构,1线程操作期间,其他线程修改了A.next,1线程比较后自然以为是预期值,判断true,继续操作(解决办法加入版本号标识,比较的不仅仅是A的值还有A的版本号)
2):自旋导致cpu压力
2.悲观锁--总是假设最坏的情况,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会阻塞直到它拿到锁。应用场景可以抽象成如下图
可重入锁:获取到外函数的锁时,内部函数的锁也获取到了
独占锁--每次只有一个线程能拿到锁(比如synchronize 和reentrantLock)如上图
共享锁--多个线程拿到锁(ReentrantReadWriteLock )如下图,3个读线程都获取锁,但是不允许读写线程和写写线程同时都持有锁,理由很简单。
公平锁--后续等待线程是一个FIFO队列,先排队的先获取锁
非公平锁--线程不排队(默认,效率高)