全国网站建设人员数量,西安php网站建设,宝安网站建设制作,wordpress 画廊 插件悲观锁和乐观锁详细
悲观锁
悲观锁就是悲观的思想#xff0c;他认为数据每一次被访问的时候都会被上锁#xff0c;所以每次获得锁的时候都会上锁#xff0c;这样其他线程想要获取这个锁的时候就会被堵塞#xff0c;要等待上一个线程锁的释放。也就是说这个线程只一次只…悲观锁和乐观锁详细
悲观锁
悲观锁就是悲观的思想他认为数据每一次被访问的时候都会被上锁所以每次获得锁的时候都会上锁这样其他线程想要获取这个锁的时候就会被堵塞要等待上一个线程锁的释放。也就是说这个线程只一次只给一个线程使用其他线程会被堵塞。当上一个线程使用完其他线程就可以竞争到这个锁。
在高并发的场景下激烈的锁景长会造成线程堵塞大佬的堵塞线程会导致线程的上下文切换会增加系统性能的消耗而且悲观锁还有可能存在死锁的问题影响代码的运行。
悲观锁的每次开销是固定的。
什么是乐观锁
乐观锁每次都是假设的最好的情况它认为资源每次被访问的时候不会被修改线程可以不停的执行无序加锁无序等待只是提交修改数据的时候需要验证一下我们的医院是否被其他的县城修改了下面CAS算法会详细介绍。比如我们的AtomicInteger、LongAdder就是使用我们乐观锁的思想。
在高并发中乐观锁不会出现线程堵塞和思索的问题性能会比悲观锁性能更好一点但是如果突然频繁发生写占比非常多的业务情况回频繁失败和重试这就会造成我们CPU飙升影响我们的应能。乐观锁的使用场景都是写比较少的地方。
在我们乐观锁是使用了版本号机制和CAS算法实现的 但是内部使用的CAS算法更多一点。
版本号控制器
版本号就是在数据表种加一个数据版本号version字段如果我们的数据修改成功我们的version会自加1。当线程A要更新数据的时候会读取当前的版本号在提交数据的时候会拿我们读到的版本号和我们表种的版本号是否一样如果一样的话就会更新然后version否则就重试更新操作直到更新成功。
CAS算法
CAS就是Compare And Swap比较与交换用户乐观锁当中被广泛用到个大框架CAS的思想很简单就是用一个预期值和要更新的值进行比较两者相等就会更新
CAS是一个原子操作底层依赖一条CPu的原子指令。
原子操作就是一旦开始就不能被打断直到操作完成
CASCompare And Swap涉及到3哥操作数
**V**需要更新的变量值
E: 预期的值
**N**拟写入的新值(新的值)
当V的值等于E的时候CAS会通过原子方式用N来更新V如果不相等那么就说明其他线程更新了V当前线程就会放弃更新。
乐观锁存在的问题
ABA问题
ABA的问题i就是我们乐观锁最常见的问题。如果一个变量V初次读取的时候是A然后准备赋值的时候检查也是A这个时候我们不能说明它没有被其他线程修改过因为很可能这时候其他线程把这个值修改成了B然后有被修改成A这时候CAS就会判定他没有被修改。
ABA的解决思路是在变量前面追加一个时间戳在JDK1.5以后的AtomicStampedReference类就是用来解决ABA问题的其中的compareAndSet就是检测我们当前的引用是否等于预期的引用如果标志相等就更新。
循环时间长开销大。
因为CAs经常会用到自选操作进行重试如果不成功就会循环执行到成功为止如果长时间不成功就会给我们的CPU带来很大的压力。
只能对一个共享变量进行原子操作
CAS支队单个贡献变量优先当操作涉及多个共享变量的时候CAS就会无效但是JDK1.5的时候开始提供了AtomicReference类保证引用对象之间的原子性我们也可以把多个变量放到一个对线里进行CAS操作所以我们可以使用锁或者利用AtomicReference类把多个共享变量合并成一个共享变量进行操作。