JAVA如何在线程中加锁(四种方法)

article/2025/10/20 21:24:42

JAVA多线程锁

线程的生命周期

在这里插入图片描述
​ 总共六种状态,可归结为五种,线程的最终是死亡,阻塞不是最终状态,只是一个临时状态。只有调用了start方法,线程才进入就绪阶段。

//新生 ​ NEW,
//运行​ RUNNABLE,
//阻塞​ BLOCKED,
//等待,死死地等​ WAITING,
//超时等待​ TIMED_WAITING,
//终止​ TERMINATED;
Wait/sleep的区别
1、来自于不同的类
wait—>object
Sleep—>Thread//一般不使用,企业一般使用TimeUnit.time.sleep( )
2、关于锁的释放
wait会释放锁,sleep不会释放锁,必须sleep足够的时间
3、适用范围是不同的
Wait:必须在同步代码块中使用
sleep:可以在任何地方使用
4、是否需要捕获异常
wait:不需捕获异常
sleep:需要捕获异常——如果等待过久
需要使用锁的原因:当多个线程操作一个共同资源(共享数据)的时候,可能会出现错误异常。
举例:售票员问题,一共一百张票,三个售票窗口进行售票,错误展示:

//多线程模拟售票问题
import java.util.concurrent.TimeUnit;public class Windows {public static void main(String[] args) {//创建三个线程,线程操纵资源类Ticket ticket = new Ticket();for(int i=0;i<3;i++){new Thread(()->{try {ticket.sell();} catch (InterruptedException e) {e.printStackTrace();}},"售票员"+String.valueOf(i)).start();}}
}
//资源类
class Ticket{private int num=100;//总共100张票public void sell() throws InterruptedException {while(num>0){System.out.println(Thread.currentThread().getName()+"卖票,票号为:"+(num--));//为了创造一些异常,让线程到此处sleep阻塞一下1TimeUnit.SECONDS.sleep(1);}}
}

在这里插入图片描述

如何解决此类,多线程操作同一数据的问题?

解决办法①synchronized关键字②lock锁

Synchronized关键字

①synchronized关键字修饰方法②synchronized关键字修饰代码块

synchronized关键字修饰方法

代码中只需要将资源类被调用的方法前加上修饰的关键字:synchronized

使用条件:如果操作共享数据的代码完整的声明在一个方法中,可以使用此方法,将方法声明为同步的

关于同步方法的总结:

  1. 同步方法仍然涉及到同步监视器,只是不需要我们显式的声明
  2. 非静态的同步方法,其同步监视器是:this(当前类的对象)

​ 静态同步方法:同步监视器是:当前类本身(类.class( ))

//资源类
class Ticket{private int num=100;//总共100张票public synchronized void sell() throws InterruptedException {//此时用synchronized修饰方法sell(),其同步监视器是:this(当前类的对象),由于使用的是while(num>0){System.out.println(Thread.currentThread().getName()+"卖票,票号为:"+(num--));//为了创造一些异常,让线程到此处sleep阻塞一下TimeUnit.MILLISECONDS.sleep(10);}}
}

此时不会出现重票问题!

synchronized关键字修饰代码块

使用格式:
synchronized(同步监视器){
//需要被同步的代码
}

说明:1. 操作共享数据的代码,即为需要被同步的代码——>此时注意不可包含多了,也不可包含少了

  1. 共享数据:多个线程共同操作的变量—例子中的票数num
  2. 同步监视器:俗称:锁,可以为任何一个类的对象。要求:多个线程必须要共用同一把锁
//资源类
class Ticket{private int num=100;//总共100张票public void sell() throws InterruptedException {synchronized (this){//此时使用synchronized修饰代码块while (num > 0) {System.out.println(Thread.currentThread().getName() + "卖票,票号为:" + (num--));//为了创造一些异常,让线程到此处sleep阻塞一下1TimeUnit.MILLISECONDS.sleep(10);}}}
}

需要注意的点:
死锁:
1:不同线程分别占用对方需要的同步资源不放,都在等待对方放弃自己需要的同步资源,就形成了线程的死锁。
2:出现死锁后,不会出现异常,不会出现提示,只是所有的线程都处于阻塞状态无法继续
使用同步时,要避免出现死锁
解决办法:
1:专门的算法、原则
2:尽量减少同步资源的定义
3:尽量避免嵌套同步

Lock锁

1:从JDK5开始,Java提供了更加强大的同步机制——通过显示定义同步锁对象来实现同步,同步锁使用Lock对象充当
2:java.util.concurrent.locks.Lock接口是控制多个线程对共享资源进行访问的工具,锁提供了对共享资源的独占访问,每次只能有一个线程和lock对象加锁,线程开始访问共享资源之前应当先获得Lock对象
3:ReentrantLock类实现了Lock,它拥有与synchronized相同的并发性和内存语义,在实现线程安全的控制中,比较常用的是ReentrantLock,可以显式加锁、释放锁

lock锁操作三部曲:
1、newReentrantLock();
2、lock.lock();//加锁(try内部)
3、finally=>lock.unlock();//解锁
API中官方解释:
在这里插入图片描述
在这里插入图片描述

公平锁:十分公平;可以先来后到

非公平锁:十分不公平,可以插队(默认)

Lock锁的使用代码展示:

//资源类
class Ticket{private int num=100;//总共100张票Lock lock=new ReentrantLock();//ReentrantLock:lock接口的实现类之一public void sell() throws InterruptedException {try {lock.lock();while (num > 0) {System.out.println(Thread.currentThread().getName() + "卖票,票号为:" + (num--));//为了创造一些异常,让线程到此处sleep阻塞一下TimeUnit.MILLISECONDS.sleep(10);}} catch (InterruptedException e) {e.printStackTrace();} finally {lock.unlock();}}
}
//此处使用Lock锁对操作进行了上锁,保证多线程操作下数据仍然安全

相比较于synchronized关键字,lock锁的优势在哪里?使用生产者消费者问题进行判断比较

线程之间的通信问题:生产者与消费者,要求:线程交替执行 A B操作同一个变量num=0;

可能出现的异常:IllegalMonitorStateException - 如果当前线程不是此对象的监视器的所有者。 抛出以表示线程已尝试在对象的监视器上等待或通知其他线程等待对象的监视器,而不拥有指定的监视器。

/** 线程之间的通信问题:生产者,消费者问题* 线程交替执行 A B操作同一个变量num=0;* A num+1;* B num-1;* */
public class ProductQuestion {public static void main(String[] args) {//创造两个线程,分别进行商品的生产和商品的消费Product product = new Product();new Thread(()->{for(int i=0;i<10;i++) {try {product.produce();} catch (InterruptedException e) {e.printStackTrace();}}},"A").start();new Thread(()->{for(int i=0;i<10;i++) {try {product.buy();} catch (InterruptedException e) {e.printStackTrace();}}},"B").start();}
}
//资源类:
class Product{private int num=0;//等待-业务-通知//不使用synchronized修饰的话,会报错,IllegalMonitorStateException - 如果当前线程不是此对象的监视器的所有者。 抛出以表示线程已尝试在对象的监视器上等待或通知其他线程等待对象的监视器,而不拥有指定的监视器。 public synchronized void produce() throws InterruptedException {if(num!=0){//商品个数不为0,当前线程需要等待this.wait();}//为0则操作num++;System.out.println(Thread.currentThread().getName()+"生产商品,当前剩余商品:"+num);//通知可以进行消费this.notifyAll();//通知其他线程可以进行商品的消费}public synchronized void buy() throws InterruptedException {if(num==0){//此时没有商品,需要等待this.wait();}//不为0则可以进行操作num--;System.out.println(Thread.currentThread().getName()+"消费商品,当前剩余商品:"+num);this.notifyAll();//通知其他线程可以生产商品}
}

结果:
在这里插入图片描述

思考:如果还是此题的背景,换为四个线程,两个生产,两个消费还可行吗?

  public static void main(String[] args) {//创造两个线程,分别进行商品的生产和商品的消费Product product = new Product();new Thread(()->{for(int i=0;i<10;i++) {try {product.produce();} catch (InterruptedException e) {e.printStackTrace();}}},"A").start();new Thread(()->{for(int i=0;i<10;i++) {try {product.buy();} catch (InterruptedException e) {e.printStackTrace();}}},"B").start();new Thread(()->{for(int i=0;i<10;i++) {try {product.produce();} catch (InterruptedException e) {e.printStackTrace();}}},"C").start();new Thread(()->{for(int i=0;i<10;i++) {try {product.buy();} catch (InterruptedException e) {e.printStackTrace();}}},"D").start();}

结果:
在这里插入图片描述

产生错误原因分析:
在这里插入图片描述

调整方式,将被调用方法中的if判断改为while即可

//资源类:
class Product{private int num=0;//等待-业务-通知public synchronized void produce() throws InterruptedException {while (num!=0){//此时将判断语句改为while,而不是if,因为if只判断一次,有可能会造成虚假唤醒。//商品个数不为0,当前线程需要等待this.wait();}//为0则操作num++;System.out.println(Thread.currentThread().getName()+"生产商品,当前剩余商品:"+num);//通知可以进行消费this.notifyAll();//通知其他线程可以进行商品的消费}public synchronized void buy() throws InterruptedException {while (num==0){//此时没有商品,需要等待this.wait();}//不为0则可以进行操作num--;System.out.println(Thread.currentThread().getName()+"消费商品,当前剩余商品:"+num);this.notifyAll();//通知其他线程可以生产商品}

结果如下:
在这里插入图片描述

使用JUC解决生产消费者问题

synchronized中使用wait( )和notifyAll( )来实现此问题
在这里插入图片描述

在Lock中使用condition接口的实现类来取得相同的效果
在这里插入图片描述
在这里插入图片描述
condition接口的实例——一个实例本质上绑定一个锁!

//资源类:
class Products{private int num=0;Lock lock=new ReentrantLock();Condition notNull=lock.newCondition();//此时condition取代了同步监视器//等待-业务-通知public void produce() {lock.lock();try {while (num!=0){//商品个数不为0,当前线程需要等待notNull.await();}//为0则操作num++;System.out.println(Thread.currentThread().getName()+"生产商品,当前剩余商品:"+num);//通知可以进行消费notNull.signalAll();} catch (InterruptedException e) {e.printStackTrace();} finally {lock.unlock();}}public void buy() {lock.lock();try {while (num==0){//此时没有商品,需要等待notNull.await();}//不为0则可以进行操作num--;System.out.println(Thread.currentThread().getName()+"消费商品,当前剩余商品:"+num);notNull.signalAll();//通知其他线程可以生产商品} catch (InterruptedException e) {e.printStackTrace();} finally {lock.unlock();}}
}

此时结果仍然是0和1交替进行生产和消费,Lock和synchronized的区别,有一些操作lock可以做到而synchronized无法做到——精确唤醒线程,此时需要创建多个condition对象!

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;/*
* 要求:执行完A操作——>执行B操作——>执行C操作
* */
public class ConditionTest {public static void main(String[] args) {Something something = new Something();new Thread(()->{for(int i=0;i<5;i++) {try {something.printA();} catch (InterruptedException e) {e.printStackTrace();}}},"1").start();new Thread(()->{for(int i=0;i<5;i++) {try {something.printB();} catch (InterruptedException e) {e.printStackTrace();}}},"2").start();new Thread(()->{for(int i=0;i<5;i++) {try {something.printC();} catch (InterruptedException e) {e.printStackTrace();}}},"3").start();}}class Something{private int num=1;Lock lock=new ReentrantLock();Condition conditionA=lock.newCondition();Condition conditionB=lock.newCondition();Condition conditionC=lock.newCondition();//判断,等待,执行,通知public void printA() throws InterruptedException {lock.lock();try {while(num!=1){conditionA.await();}System.out.println(Thread.currentThread().getName()+":"+"AAAAA");num=2;//指定num为2conditionB.signal();} catch (InterruptedException e) {e.printStackTrace();} finally {lock.unlock();}}public void printB() throws InterruptedException {lock.lock();try {while(num!=2){conditionB.await();}System.out.println(Thread.currentThread().getName()+":"+"BBBBB");num=3;//指定num为3conditionC.signal();} catch (InterruptedException e) {e.printStackTrace();} finally {lock.unlock();}} public void printC() throws InterruptedException {lock.lock();try {while(num!=3){conditionC.await();}System.out.println(Thread.currentThread().getName()+":"+"CCCCC");num=1;//指定num为1conditionA.signal();} catch (InterruptedException e) {e.printStackTrace();} finally {lock.unlock();}}
}

在这里插入图片描述

synchronized 和 Lock的区别

  1. synchronized 内置的Java关键字,lock是一个Java类
  2. synchronized无法判断获取锁的状态,lock可以判断是否获取到了锁
  3. synchronized会自动释放锁,lock必须要手动释放锁!如果不释放锁——死锁
  4. synchronized 线程1(获得锁,阻塞)、线程2(等待,傻傻的等待),lock锁就不一定会等待下去
  5. synchronized 可重入锁,不可以中断的,非公平;lock 可重入锁,可以判断锁,非公平(可以自己设置为公平锁,非公平是默认状态)
  6. synchronized 适合锁少量的代码同步问题,Lock适合锁大量的同步代码

http://chatgpt.dhexx.cn/article/WcOFdXNY.shtml

相关文章

大数据平台_大数据应用场景有哪些

大数据时代的出现&#xff0c;简单的讲是海量数据同完美计算能力结合的结果&#xff0c;确切的说是移动互联网、物联网产生了海量的数据&#xff0c;大数据计算技术完美地解决了海量数据的收集、存储、计算、分析的问题。一些公司也成立了大数据部门&#xff0c;大数据得到了企…

银行业9大数据科学应用案例

在银行业中使用数据科学不仅仅是一种趋势,它已成为保持竞争的必要条件。 银行必须认识到, 大数据技术可以帮助他们有效地集中资源,做出更明智的决策并提高绩效。 以下我们罗列银行业使用的数据科学用例清单, 让您了解如何处理大量数据以及如何有效使用数据。 [TOC] 1 欺诈识…

某银行大数据体系架构设计与演进

近年来&#xff0c;随着大数据与人工智能相关技术的迅速发展&#xff0c;新技术逐步在全社会各行各业得到应用。银行业作为一个高度信息化的行业&#xff0c;首当其冲面临着互联网新技术应用的挑战。民生银行在 2013 年开始布局分布式、大数据及人工智能技术等领域&#xff0c;…

图解大数据 | 大数据生态与应用导论

作者&#xff1a;韩信子[ShowMeAI](https://www.showmeai.tech 教程地址&#xff1a;https://www.showmeai.tech/tutorials/84 本文地址&#xff1a;https://www.showmeai.tech/article-detail/167 声明&#xff1a;版权所有&#xff0c;转载请联系平台与作者并注明出处 收藏S…

大数据应用于生活,目前主要应用在哪些领域?

如果提到“大数据”时&#xff0c;你会想到什么?也许大部分人会联想到庞大的服务器集群;或者联想到销售商提供的一些个性化的推荐和建议。 如今大数据的深度和广度远不止这些&#xff0c;大数据已经在人类社会实践中发挥着巨大的优势&#xff0c;其利用价值也超出我们的想像。…

大数据应用管理模式及内容

通过调研&#xff0c;数据应用管理可总结为分散管理型、职能复用型、集中管理型三种模式&#xff0c;数据应用管理模式中重点关注组织管理、需求管理、建设管理、成果管理四大领域。 &#xff08;1&#xff09; 管理模式 分散管理型&#xff1a;各部门分散开展数据应用&#xf…

大数据应用于各个行业,大数据在各行各业的具体应用是什么?

大数据无处不在&#xff0c;大数据应用于各个行业&#xff0c;包括金融、汽车、餐饮、电信、能源、体能和娱乐等在内的社会各行各业都已经融入了大数据的印迹&#xff0c;下面详细介绍一下大数据在各行各业的具体应用。      制造业&#xff0c;利用工业大数据提升制造业水…

大数据应用的重要性体现在方方面面

大数据应用的重要性&#xff0c;自全国提出“数据中国”的概念以来&#xff0c;我们周围默默地在发挥作用的大数据逐渐深入人们的心中&#xff0c;大数据的应用也越来越广泛&#xff0c;具体到金融、汽车、餐饮、电信、能源、体育和娱乐等领域&#xff0c;下面就通过本文&#…

4大案例分析金融机构的大数据应用

就“大数据金融”思维利用而言&#xff0c;国外金融机构有着十足丰富的体现&#xff0c;已经将大数据技术在风险控制、运营管理、销售支持及商业模式创新等领域进行了全面的尝试。 案例一&#xff1a;汇丰银行-风险管理 汇丰银行在防范信用卡和借记卡欺诈的基础上&#xff0c;利…

金融业大数据应用场景

如果能够引入外部数据&#xff0c;还可以进一步加快数据价值的变现。外部数据中比较好的有社交数据、电商交易数据、移动大数据、运营商数据、工商司法数据、公安数据、教育数据和银联交易数据等。 大数据在金融行业的应用范围较广&#xff0c;典型的案例有花旗银行利用 IBM 沃…

【行业|分析】大数据对于银行七大应用

如今,Hadoop几乎存在于各个方面,其通过利用大数据来分析信息和增加竞争力。许多金融机构和公司已经开始使用Hadoop成功地解决问题,即便他们本没有计划这样做。因为如果他们不这样做,就会面临市场份额损失的巨大风险。以下是一些特别有趣且重要的大数据和Hadoop用例。 诈骗侦…

银行大数据风控平台的建设要点与应用

金融行业是经营风险的行业&#xff0c;风险控制能力是金融机构的核心竞争力。通常而言&#xff0c;金融机构一般是通过给客户的信用状况评分来计量贷款违约的可能性&#xff0c;并通过客户的风险水平进行利率定价。 而传统的信用测算主要是利用历史借贷数据和财务数据对借款人的…

浅谈大数据如何应用?

大数据所面临的五大问题中最后一个是大数据应用&#xff0c;也是大数据问题的具象和最终展现形式。如果用更高度的概括来表述大数据的生命周期&#xff0c;可以归纳为&#xff1a;大数据来源大数据技术大数据应用。三者缺一不可、彼此相承&#xff0c;见下图&#xff1a; ** …

银行大数据风控管理针对哪些应用场景?

银行是经营风险的企业&#xff0c;在风险识别、衡量、定价和防范等方面的能力水平&#xff0c;是判断银行是否具备核心竞争力的关键。随着社会信息化、数字化体系建设&#xff0c;银行风险管理也必将迎来“数智化”时代。 其实&#xff0c;银行业务的申请、交易、营销等环节都…

大数据技术在银行业应用中,主要有哪些优势,面临哪些难题?

大数据技术在银行业应用中的主要优势与难题 经济社会的三个重要组成要素&#xff1a;产品、信息、资金渗透于互联网时代的诸多环节&#xff0c;互联网时代的激烈竞争当中&#xff0c;电商、银行、物流三大类别企业代表着三种要素的重要占有者&#xff0c;三者都希望成为主宰着…

大数据技术在银行业中的应用场景,主要有哪些?

2、大数据技术在银行业中的主要应用场景 (一)大数据时代下银行的精准营销 按照单个客户个性化的营销方案和沟通服务体系&#xff0c;金融机构依照信息化技术手段可以建立起精确的营销方案以实现对个人客户的精准营销(PrecisionMarketing)。这种建立在精准定位基础之上的营销活…

PyCharm | 社区版—页面汉化方法

如何不适用汉化包汉化PyCharm&#xff1f; 下图PyCharm版本&#xff1a;2020.3 社区版 主页面 File —> Settings —> plugins—> 输入框输入chinese —> Install —> apple —>Ok 重启软件后

猿如意|手把手教你下载、安装和配置PyCharm社区版

手把手教你使用猿如意下载、安装和配置PyCharm社区版&#xff0c;希望能帮助到有需要的童鞋。 文章目录 前言一、下载安装猿如意二、安装PyCharm社区版1.通过猿如意找到PyCharm下载位置2.安装PyCharm 三、对PyCharm社区版进行简单设置1.设置PyCharm社区版为中文2.安装第三方Pyt…

关于 Pycharm专业版 安装教程,简单好用

二、&#x1f3d4;目前我们的Pycharm2021.3版本已经安装完成 1.&#x1f412;下面&#xff0c;我们需要将压缩文件里的text1.txt文件选择自己合适的路径&#xff0c;在这里我们选择Windows&#xff0c; 2.&#x1f412;下面我们需要将此路径进行一个复制&#xff0c;打开Pychar…

猿如意中的【PyCharm社区版】工具详情介绍

猿如意中的【PyCharm社区版】工具详情介绍&#xff0c;手把手教你使用猿如意下载、安装和配置【PyCharm社区版】&#xff0c;希望能帮助到有需要的童鞋。 文章目录 前言一、猿如意介绍二、PyCharm社区版开发工具简介1.【PyCharm专业版】和【PyCharm社区版】的功能区别2.【PyCha…