iis服务器助手广告广告
返回顶部
首页 > 资讯 > 精选 >Java并发编程中的悲观锁和乐观锁机制
  • 334
分享到

Java并发编程中的悲观锁和乐观锁机制

2023-06-02 09:06:54 334人浏览 安东尼
摘要

这篇文章主要介绍“Java并发编程中的悲观锁和乐观锁机制”,在日常操作中,相信很多人在java并发编程中的悲观锁和乐观锁机制问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Java并发编程中的悲观锁和乐观锁机制

这篇文章主要介绍“Java并发编程中的悲观和乐观锁机制”,在日常操作中,相信很多人在java并发编程中的悲观锁和乐观锁机制问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Java并发编程中的悲观锁和乐观锁机制”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

一、资源和加锁

1、场景描述

多线程并发访问同一个资源问题,假如线程A获取变量之后修改变量值,线程C在此时也获取变量值并且修改,两个线程同时并发处理一个变量,就会导致并发问题。

Java并发编程中的悲观锁和乐观锁机制

这种并行处理数据库的情况在实际的业务开发中很常见,两个线程先后修改数据库的值,导致数据有问题,该问题复现的概率不大,处理的时候需要对整个模块体系有概念,才能容易定位问题。

2、演示案例

public class LockThread01 {    public static void main(String[] args) {        CountAdd countAdd = new CountAdd() ;        AddThread01 addThread01 = new AddThread01(countAdd) ;        addThread01.start();        AddThread02 varThread02 = new AddThread02(countAdd) ;        varThread02.start();    }}class AddThread01 extends Thread {    private CountAdd countAdd  ;    public AddThread01 (CountAdd countAdd){        this.countAdd = countAdd ;    }    @Override    public void run() {        countAdd.countAdd(30);    }}class AddThread02 extends Thread {    private CountAdd countAdd  ;    public AddThread02 (CountAdd countAdd){        this.countAdd = countAdd ;    }    @Override    public void run() {        countAdd.countAdd(10);    }}class CountAdd {    private Integer count = 0 ;    public void countAdd (Integer num){        try {            if (num == 30){                count = count + 50 ;                Thread.sleep(3000);            } else {                count = count + num ;            }            System.out.println("num="+num+";count="+count);        } catch (Exception e){            e.printStackTrace();        }    }}

这里案例演示多线程并发修改count值,导致和预期不一致的结果,这是多线程并发下最常见的问题,尤其是在并发更新数据时。

出现并发的情况时,就需要通过一定的方式或策略来控制在并发情况下数据读写的准确性,这被称为并发控制,实现并发控制手段也很多,最常见的方式是资源加锁,还有一种简单的实现策略:修改数据前读取数据,修改的时候加入限制条件,保证修改的内容在此期间没有被修改。

二、锁的概念简介

1、锁机制简介

并发编程中一个最关键的问题,多线程并发处理同一个资源,防止资源使用的冲突一个关键解决方法,就是在资源上加锁:多线程序列化访问。锁是用来控制多个线程访问共享资源的方式,锁机制能够让共享资源在任意给定时刻只有一个线程任务访问,实现线程任务的同步互斥,这是最理想但性能最差的方式,共享读锁的机制允许多任务并发访问资源。

2、悲观锁

悲观锁,总是假设每次每次被读取的数据会被修改,所以要给读取的数据加锁,具有强烈的资源独占和排他特性,在整个数据处理过程中,将数据处于锁定状态,例如synchronized关键字的实现就是悲观机制。

Java并发编程中的悲观锁和乐观锁机制

悲观锁的实现,往往依靠数据库提供的锁机制,只有数据库层提供的锁机制才能真正保证数据访问的排他性,否则,即使在本系统中实现了加锁机制,也无法保证外部系统不会修改数据,悲观锁主要分为共享读锁和排他写锁。

排他锁基本机制:又称写锁,允许获取排他锁的事务更新数据,阻止其他事务取得相同的资源的共享读锁和排他锁。若事务T对数据对象A加上写锁,事务T可以读A也可以修改A,其他事务不能再对A加任何锁,直到T释放A上的写锁。

3、乐观锁

乐观锁相对悲观锁而言,采用更加宽松的加锁机制。悲观锁大多数情况下依靠数据库的锁机制实现,以保证操作最大程度的独占性。但随之而来的就是数据库性能的大量开销,特别是对长事务的开销非常的占资源,乐观锁机制在一定程度上解决了这个问题。

Java并发编程中的悲观锁和乐观锁机制

乐观锁大多是基于数据版本记录机制实现,为数据增加一个版本标识,在基于数据库表的版本解决方案中,一般是通过为数据库表增加一个version字段来实现。读取出数据时,将此版本号一同读出,之后更新时,对此版本号加一。此时,将提交数据的版本数据与数据库表对应记录的当前版本信息进行比对,如果提交的数据版本号等于数据库表当前版本号,则予以更新,否则认为是过期数据。乐观锁机制在高并发场景下,可能会导致大量更新失败的操作。

乐观锁的实现是策略层面的实现:CAS(Compare-And-Swap)。当多个线程尝试使用CAS同时更新同一个变量时,只有其中一个线程能成功更新变量的值,而其它线程都失败,失败的线程并不会被挂起,而是被告知这次竞争中失败,并可以再次尝试。

4、机制对比

悲观锁本身的实现机制就以损失性能为代价,多线程争抢,加锁、释放锁会导致比较多的上下文切换和调度延时,加锁的机制会产生额外的开销,还有增加产生死锁的概率,引发性能问题。

乐观锁虽然会基于对比检测的手段判断更新的数据是否有变化,但是不确定数据是否变化完成,例如线程1读取的数据是A1,但是线程2操作A1的值变化为A2,然后再次变化为A1,这样线程1的任务是没有感知的。

悲观锁每一次数据修改都要上锁,效率低,写数据失败的概率比较低,比较适合用在写多读少场景。

乐观锁并未真正加锁,效率高,写数据失败的概率比较高,容易发生业务形异常,比较适合用在读多写少场景。

是选择牺牲性能,还是追求效率,要根据业务场景判断,这种选择需要依赖经验判断,不过随着技术迭代,数据库的效率提升,集群模式的出现,性能和效率还是可以两全的。

三、Lock基础案例

1、Lock方法说明

lock:执行一次获取锁,获取后立即返回;

lockInterruptibly:在获取锁的过程中可以中断;

tryLock:尝试非阻塞获取锁,可以设置超时时间,如果获取成功返回true,有利于线程的状态监控

unlock:释放锁,清理线程状态;

newCondition:获取等待通知组件,和当前锁绑定;

2、应用案例

import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;public class LockThread02 {    public static void main(String[] args) {        LockNum lockNum = new LockNum() ;        LockThread lockThread1 = new LockThread(lockNum,"TH1");        LockThread lockThread2 = new LockThread(lockNum,"TH2");        LockThread lockThread3 = new LockThread(lockNum,"TH3");        lockThread1.start();        lockThread2.start();        lockThread3.start();    }}class LockNum {    private Lock lock = new ReentrantLock() ;    public void getNum (){        lock.lock();        try {            for (int i = 0 ; i < 3 ; i++){                System.out.println("ThreadName:"+Thread.currentThread().getName()+";i="+i);            }        } finally {            lock.unlock();        }    }}class LockThread extends Thread {    private LockNum lockNum ;    public LockThread (LockNum lockNum,String name){        this.lockNum = lockNum ;        super.setName(name);    }    @Override    public void run() {        lockNum.getNum();    }}

这里多线程基于Lock锁机制,分别依次执行任务,这是Lock的基础用法,各种api的详解,下次再说。

3、与synchronized对比

基于synchronized实现的锁机制,安全性很高,但是一旦线程失败,直接抛出异常,没有清理线程状态的机会。显式的使用Lock语法,可以在finally语句中最终释放锁,维护相对正常的线程状态,在获取锁的过程中,可以尝试获取,或者尝试获取锁一段时间。

四、源代码地址

GitHub·地址https://github.com/cicadasmile/java-base-parentGitEE·地址Https://gitee.com/cicadasmile/java-base-parent

到此,关于“Java并发编程中的悲观锁和乐观锁机制”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注编程网网站,小编会继续努力为大家带来更多实用的文章!

--结束END--

本文标题: Java并发编程中的悲观锁和乐观锁机制

本文链接: https://www.lsjlt.com/news/229603.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Java并发编程中的悲观锁和乐观锁机制
    这篇文章主要介绍“Java并发编程中的悲观锁和乐观锁机制”,在日常操作中,相信很多人在Java并发编程中的悲观锁和乐观锁机制问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Java并发编程中的悲观锁和乐观锁机制...
    99+
    2023-06-02
  • Java并发编程的悲观锁和乐观锁机制
    本篇内容主要讲解“Java并发编程的悲观锁和乐观锁机制”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Java并发编程的悲观锁和乐观锁机制”吧!一、资源和加锁1、场景描述多线程并发访问同一个资源问...
    99+
    2023-06-16
  • Java悲观锁和乐观锁机制是什么
    本篇内容主要讲解“Java悲观锁和乐观锁机制是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Java悲观锁和乐观锁机制是什么”吧!1、锁机制简介并发编程中一个最关键的问题,多线程并发处理同一...
    99+
    2023-06-02
  • java中乐观锁与悲观锁的概念
    这篇文章主要介绍“java中乐观锁与悲观锁的概念”,在日常操作中,相信很多人在java中乐观锁与悲观锁的概念问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”java中乐观锁与悲观锁的概念”的疑惑有所帮助!接下来...
    99+
    2023-06-19
  • 浅谈一下Java中的悲观锁和乐观锁
    目录悲观锁(Pessimistic Locking)悲观锁存的问题:乐观锁乐观锁存在的问题悲观锁和乐观锁的对比总结悲观锁和乐观锁是面试高频问题之一,本文将对悲观锁和乐观锁简单的进行一...
    99+
    2023-05-16
    Java悲观锁 Java乐观锁
  • MySQL中乐观锁和悲观锁的区别
    这篇文章将为大家详细讲解有关MySQL中乐观锁和悲观锁的区别,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。悲观锁在关系数据库管理系统中,悲观并发控制(悲观锁...
    99+
    2024-04-02
  • Java多线程之悲观锁与乐观锁
    目录1. 悲观锁存在的问题2. 通过CAS实现乐观锁3. 不可重入的自旋锁4. 可重入的自旋锁总结问题: 1、乐观锁和悲观锁的理解及如何实现,有哪些实现方式? 2、什么是乐观锁和悲观...
    99+
    2024-04-02
  • Java中的乐观锁和悲观锁简单介绍
    这篇文章主要介绍“Java中的乐观锁和悲观锁简单介绍”,在日常操作中,相信很多人在Java中的乐观锁和悲观锁简单介绍问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Java中的乐观锁和悲观锁简单介绍”的疑惑有所...
    99+
    2023-06-02
  • 详解Java中的悲观锁与乐观锁
    目录一、悲观锁二、乐观锁三、CAS四、AtomicXXX五、CAS中的ABA问题六、ABA问题解决方案七、使用CAS会引起的问题八、Synchronized锁优化九、偏向锁十、轻量级...
    99+
    2024-04-02
  • java中悲观锁和乐观锁有什么区别
    本篇文章给大家分享的是有关java中悲观锁和乐观锁有什么区别,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。Java可以用来干什么Java主要应用于:1. web开发;2. An...
    99+
    2023-06-14
  • MySQL中乐观锁和悲观锁是什么
    这篇文章给大家分享的是有关MySQL中乐观锁和悲观锁是什么的内容。小编觉得挺实用的,因此分享给大家做个参考。一起跟随小编过来看看吧。数据库管理系统中并发控制的任务是确保在多个事务同时存取数据库中同一数据不破...
    99+
    2024-04-02
  • 一文秒懂Java中的乐观锁 VS 悲观锁
    乐观锁 VS 悲观锁 悲观锁:总是假设最坏的情况,每次取数据时都认为其他线程会修改,所以都会加锁(读锁、写锁、行锁等),当其他线程想要访问数据时,都需要阻塞挂起。 乐观锁:总是认为不...
    99+
    2024-04-02
  • Java并发问题之乐观锁与悲观锁的示例分析
    这篇文章将为大家详细讲解有关Java并发问题之乐观锁与悲观锁的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。首先介绍一些乐观锁与悲观锁:悲观锁:总是假设最坏的情况,每次去拿数据的时候都认为别人会修...
    99+
    2023-05-30
    java
  • Java中的悲观锁与乐观锁怎么掌握
    要掌握Java中的悲观锁和乐观锁,可以遵循以下步骤:1. 了解悲观锁和乐观锁的概念:- 悲观锁(Pessimistic Lockin...
    99+
    2023-08-12
    Java
  • mysql中如何使用乐观锁和悲观锁
    MySQL中可以使用SELECT ... FOR UPDATE语句来实现悲观锁。这个语句会在查询时锁定被查询的行,在事务结束前都不会释放锁。 例如,我们可以使用以下的 SQL 语句来锁定一个特定的行: ``` BEGIN; SELE...
    99+
    2023-09-18
    mysql
  • mysql中乐观锁和悲观锁有什么区别
    mysql中乐观锁和悲观锁的区别有:1.概念不同;2.使用场景不同;3.实现方式不同;4.特点不同;mysql中乐观锁和悲观锁的区别有以下几点概念不同mysql中乐观锁是对加锁持有一种乐观的态度,可以先进行业务操作,不到最后一步不进行加锁,...
    99+
    2024-04-02
  • mysql 乐观锁和悲观锁的具体使用
    目录悲观锁介绍(百科):1如果不采用锁,那么操作方法如下:2使用悲观锁来实现:补充:MySQL select…for update的Row Lock与Tabl...
    99+
    2023-01-08
    mysql 乐观锁和悲观锁 mysql 乐观锁 mysql 悲观锁
  • mysql 乐观锁和悲观锁的具体使用
    目录悲观锁介绍(百科):1如果不采用锁,那么操作方法如下:2使用悲观锁来实现:补充:mysql select…for update的Row Lock与Table Lock乐观锁介绍:使用举例:以M...
    99+
    2023-01-09
    mysql 乐观锁和悲观锁 mysql 乐观锁 mysql 悲观锁
  • Spring Boot2+JPA之悲观锁和乐观锁实战教程
    目录前言悲观锁与并发利用SQL的for update解决并发问题利用JPA的@Lock行锁注解解决并发问题如果是@NameQuery,则可以乐观锁与并发利用version字...
    99+
    2024-04-02
  • MYSQL中悲观锁和乐观锁的作用是什么
    这篇文章给大家介绍MYSQL中悲观锁和乐观锁的作用是什么,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。  悲观锁(Pessimistic Lock)  悲观锁(Pessimistic ...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作