Java并发浅析悲观锁与乐观锁

Java并发浅析悲观锁与乐观锁

平常面试中我们总会遇到面试官提问,你知道什么是悲观锁与乐观锁吗?对于经验少的小白就会一脸懵逼,今天随笔浅析一下乐观锁与悲观锁的不同.
说锁之前,我们先了解一下并发中的上下文切换:
阿里云上的服务器,很多都是单核处理器,大家就会问,单核处理器也能做并发操作吗?其实是可以的,CPU通过给每个线程分配CPU时间片来实现这个机制。时间片是CPU分配给各个县城的时间.因为时间片非常短,所以CPU通过不停的切换线程执行,让我们觉得很流程,感觉是多个进程同时执行的,时间片一般都是几十毫秒(ms).
CPU通过是键盘分配算法来循环执行任务,当前任务执行一个时间片后会切换到下一个任务.但是时间片会记录上一个任务的状态.以便于下次切回这个任务的时候,可以继续加载这个任务。所以任务从保存再加载就是一次上下文切换.
我们先稍微介绍一下乐观锁与悲观锁:
悲观锁:假定会发生并发冲突,屏蔽一切可能违反数据完整性的操作。
乐观锁:假设不会发生并发冲突,只在提交操作时检查是否违反数据完整性。
一个线程被挂起时,加入到阻塞队列,在一定的时间或条件下,在通过notify(),notifyAll()唤醒回来。在某个资源不可用的时候,就将cpu让出,把当前等待线程切换为阻塞状态。等到资源(比如一个共享数据)可用了,那么就将线程唤醒,让他进入runnable状态等待cpu调度。这就是典型的悲观锁的实现。独占锁是一种悲观锁,synchronized就是一种独占锁,它假设最坏的情况,并且只有在确保其它线程不会造成干扰的情况下执行,会导致其它所有需要锁的线程挂起,等待持有锁的线程释放锁。
但是,由于在进程挂起和恢复执行过程中存在着很大的开销。当一个线程正在等待锁时,它不能做任何事,所以悲观锁有很大的缺点。举个例子,如果一个线程需要某个资源,但是这个资源的占用时间很短,当线程第一次抢占这个资源时,可能这个资源被占用,如果此时挂起这个线程,可能立刻就发现资源可用,然后又需要花费很长的时间重新抢占锁,时间代价就会非常的高。
所以就有了乐观锁的概念,他的核心思路就是,每次不加锁(无锁)而是假设没有冲突而去完成某项操作,如果因为冲突失败就重试(自旋锁),直到成功为止。在上面的例子中,某个线程可以不让出cpu,而是一直while循环,如果失败就重试,直到成功为止。所以,当数据争用不严重时,乐观锁效果更好。比如CAS就是一种乐观锁思想的应用。

发布了15 篇原创文章 · 获赞 4 · 访问量 22

猜你喜欢

转载自blog.csdn.net/xxb_assassin/article/details/105469889