登录信产部网站,网站设计培训基地,现在做互联网好做吗,专门做当归的网站锁策略 悲观锁乐观锁乐观锁的实现方式公平锁 vs 非公平锁 悲观锁
悲观锁总是假设最坏的情况#xff0c;认为共享资源每次被访问的时候就会出现问题#xff0c;例如共享数据被修改等#xff0c;所以每次在获取资源操作的时候都会上锁#xff0c;这样其他线程想拿到这个资源… 锁策略 悲观锁乐观锁乐观锁的实现方式公平锁 vs 非公平锁 悲观锁
悲观锁总是假设最坏的情况认为共享资源每次被访问的时候就会出现问题例如共享数据被修改等所以每次在获取资源操作的时候都会上锁这样其他线程想拿到这个资源就会阻塞直到锁被上一个持有者释放。也就是说共享资源每次只给一个线程使用其它线程阻塞用完后再把资源转让给其它线程。
synchronized ReentrantLock 等独占锁就是悲观锁思想实现的。
乐观锁
乐观锁总是假设最好的情况认为共享资源每次被访问的时候不会出现问题线程可以不停地执行无需加锁也无需等待只是在提交修改的时候去验证对应的资源数据是否被其它线程修改了具体方法可以使用版本号机制或 CAS 算法。
例如java.util.concurrent.atomic包下面的AtomicInteger、LongAdder就是使用了乐观锁的一种实现方式CAS实现。
高并发的场景下乐观锁相比悲观锁来说不存在锁竞争造成线程阻塞也不会有死锁的问题在性能上往往会更胜一筹。但是如果冲突频繁发生写占比非常多的情况会频繁失败和重试这样同样会非常影响性能导致 CPU 飙升。
不过大量失败重试的问题也是可以解决的像我们前面提到的 LongAdder以空间换时间的方式就解决了这个问题。
理论上来说
悲观锁通常多用于写比较多的情况多写场景竞争激烈这样可以避免频繁失败和重试影响性能悲观锁的开销是固定的。不过如果乐观锁解决了频繁失败和重试这个问题的话比如LongAdder也是可以考虑使用乐观锁的要视实际情况而定。乐观锁通常多用于写比较少的情况多读场景竞争较少这样可以避免频繁加锁影响性能。不过乐观锁主要针对的对象是单个共享变量参考java.util.concurrent.atomic包下面的原子变量类。
乐观锁的实现方式
版本号机制或 CAS 算法实现
CASCompare and Swap是一种轻量级的同步操作也是乐观锁的一种实现它用于实现多线程环境下的并发算法。CAS 操作包含三个操作数内存位置或者说是一个变量的引用、预期的值和新值。如果内存位置的值和预期值相等那么处理器会自动将该位置的值更新为新值否则不进行任何操作。
带版本号的 CAS也称为双重 CASDouble CAS或者版本号 CAS。具体来说每次进行 CAS 操作时不仅需要比较要修改的内存地址的值与期望的值是否相等还需要比较这个内存地址的版本号是否与期望的版本号相等。如果相等才进行修改操作。这样在修改后的值后面追加上一个版本号即使变量的值从 A 变成了 B 再变成了 A版本号也会发生变化从而避免了误判。
公平锁 vs 非公平锁
公平锁 : 锁被释放之后先申请的线程先得到锁。性能较差一些因为公平锁为了保证时间上的绝对顺序上下文切换更频繁。 非公平锁锁被释放之后后申请的线程可能会先获取到锁是随机或者按照其他优先级排序的。性能更好但可能会导致某些线程永远无法获取到锁。