最新消息: PyCharm vs VSCode,哪个更好?
您现在的位置是:群英 > 网络安全 > 数据安全 >
java乐观锁和悲观锁的含义及使用解析
admin发表于 2020-08-31 18:43 次浏览
            java乐观锁和悲观锁的含义及使用解析。之前有朋友面试时提及乐观锁和悲观锁的问题,觉得还没有详细的了解过,今天看到ConcurrentHashMap实现线程安全时即(Synchronized+CAS),深入的再次复习了CAS(乐观锁),synchronized(悲观锁)的知识点。写下知识点以作为梳理。

什么是乐观锁

         含义:所有的情况都会往好的方向发展。乐观锁在操作数据时非常乐观,认为不会有其它线程同时来修改数据,所以不会上锁。但是在更新数据时,会进行判断值是否被修改过,如果没有被修改则进行操作,否则放弃操作。乐观锁里面没有锁(lock)。

         CAS:CAS即比较与交换 ,它是乐观锁思想的一种实现方式。CAS有三个参数V(需要操作的内存地址),A(期望值),B(新的值),在进行更新操作时会判断V是否等于A (即判断这个值是否已经被其它的线程修改过),如果等于则将B值赋值给V并且返回true,否则不做操作。

         2.1. CAS在多线程的情况下:多个线程使用CAS对数据进行操作时,只有V=A的线程才能完成对V的赋值,返回true,其它失败的线程不会被挂起,而是会不断的进行循环操作(自旋->后面有解释)。所以,CAS在不使用lock 的情况下 ,也能察觉到其它线程对当前线程的影响。
         Tips: 许多CAS的操作是自旋的:如果操作不成功,会一直重试,直到操作成功(这也是它的缺点)。

         2.2 . CAS的原子操作:什么是原子——》即不可再进行分割。什么是原子性操作——》即一旦进行操作,则不能打断,直到操作完成。CAS的原子性操作是由硬件进行保障的。
         2 .3 . CAS的问题以及解决方法:
         (1)ABA问题:假如有两个线程,线1与线程1。
第一步, 线程1读取数据的值为A,
第二步,线程2则去修改数据的值为B ,
第三步,线程2修改回数据的值为A,
第四步,线程1 使用CAS操作数据。


         在第四步中,因为数据值仍然A,所以CAS操作成功,这似乎没有什么变化,但是 如果是在其它的场景下呢?比如一个栈的栈顶中,对栈顶进行多次的操作后,值虽然相同但是它已经改变了。
         解决:添加一个版本号,每次对数据进行操作后,就进行+1操作,进行CAS的比较时,除了比较V与A是否相等,还要比较版本号是否相等。
         (2)自旋问题带来的效率降低问题:
         在高竞争的环境下带来高概率的并发冲突问题,会导致失败的线程一直进行循环比较。这导致CPU开销变大。
         解决: 可以做一个退出机制,当失败的次数达到一定时,就进行退出。

         (3) CAS只能保证一个变量的原子操作。这意味着CAS在有多个变量的情况下已经不能保证线程的安全的问题。
         解决:可以使用AtomicReference把多个变量放入一个对象中进行CAS操作。

什么是悲观锁

         1,含义:认为情况都往最坏的情况进行发展。悲观锁在操作数据时,认为会有其它的线程来修改数据,所以它操作数据时会将数据锁住,等操作完成后,再解锁 。
         2,synchronized 就是悲观锁思想的实现。

使用场景:

          乐观锁 使用的场景一般是在并发冲突少、竞争不激烈中。在这种场景下乐观锁的效率要高于悲观锁,因为 悲观锁会锁住代码,其它的线程不能操作。同理,高并发下冲。突概率上升,建议使用悲观锁。
标签:java新手教程
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:mmqy2019@163.com进行举报,并提供相关证据,查实之后,将立刻删除涉嫌侵权内容。
相关信息推荐