Java多线程(二)——同步

news2024/11/24 16:37:46

这一节主要是继上次提到的线程同步三大方法:同步代码块、同步方法、Lock锁。

  1. 同步代码块,把出现线程安全问题的核心代码给上锁。

还是继上次的例子,对代码块加上synchronized ("getMoney") {}之后就不会出现线程安全问题了:

    public void getMoney(double money) {
        String names = Thread.currentThread().getName();
        System.out.println(names+"进来取钱了!");
        //会出现问题的代码块
        synchronized ("getMoney") {//同步锁对象getMoney,
            if (this.money >= money) {
                System.out.println(names + "取出" + money);
                this.money -= money;
                System.out.println(ID + "剩余" + this.money);
            } else
                System.out.println(names + "取钱" + money + " 失败," + "剩余" + this.money);
        }
    }

锁对象唯一(字符串"getMoney")不太好,会锁住其他全部非共享线程。因此建议使用共享资源作为锁对象,对于实例方法建议使用this作为锁对象。 对于静态方法建议使用字节码(类名.class)对象作为锁对象。

  1. 同步方法,出现线程安全问题的核心方法给上锁。

只需要在方法加上synchronized 修饰,这种方法就使得一整个方法加上了锁。

public synchronized void getMoney(double money){

该方法在底层是有隐式锁对象的,对于两个共享资源是不冲突的。

  1. Lock锁,一个新的锁对象Lock。

在共享资源类里面加上private final Lock lock=new ReentrantLock(); —final了,唯一不可替换的锁。所以例子中,在账户里面加上这句,同一个账户就是同一把锁。然后再取钱方法中加上lock()上锁,使用完用unlock()解锁。

    public void getMoney(double money){
        String name=Thread.currentThread().getName();
        //
        lock.lock();
        if(this.money>=money){
            System.out.println(name+"取出"+money);
            this.money-=money;
            System.out.println(ID+"剩余"+this.money);
        }
        else
            System.out.println(name+"取钱"+money+" 失败"+"剩余"+this.money);
        lock.unlock();
    }

为了防止加锁后出现异常,导致解锁问题,通常使用try...catch...finally;

lock.lock();
        try {
            if (this.money >= money) {
                System.out.println(name + "取出" + money);
                this.money -= money;
                System.out.println(ID + "剩余" + this.money);
            } else
                System.out.println(name + "取钱" + money + " 失败" + "剩余" + this.money);
        } finally {
            lock.unlock();
        }
  1. 线程通信

线程通信就是线程间相互发送数据,线程间共享一个资源即可实现线程通信,(保证线程安全的前提)。例如在生产者与消费者模型中,一个有限的空间仓库中,生产者线程生产完内容后唤醒消费者,然后停下来等待生产,消费者消费完该产品后唤醒生产者,停止消费。

线程通信的三个常见方法(Object类,当前同步锁对象进行调用):

void wait​() :让当前线程等待并释放所占锁,直到另一个线程调用notify()方法或 notifyAll()方法;

void notify​():唤醒正在等待的单个线程;

void notifyAll​():唤醒正在等待的所有线程。

  • 示例,简单的生产者与消费者模型案例:有一个亲情账户,最大金额是10,000,孩子可以取钱,父母存钱,还是假设每次都只能存取10000元为例。

  • 创建一个账户类,有存、取方法;父母进行存操作方法后,存钱成功(当账户余0)就会唤醒其他进程(让消费者进行消费)并进入等待,存钱失败(账户余10,000)就自己等待;孩子进行取操作方法后,取钱成功(当账户有钱)就会唤醒其他进程(让生产者进行生产)并进入等待,取钱失败(账户余0)就自己等待;

class account{
    private String ID;
    private double money;
    public account(){}
    public account(String id,double money){
        this.ID=id;
        this.money=money;
    }
//取
    public synchronized void getMoney(double money){
        String name=Thread.currentThread().getName();
        System.out.println(name + " 取锁  *****");
        try {
            if (this.money >= money) {
                System.out.print(name + "取出" + money+" - ");
                this.money -= money;
                System.out.println(ID + "剩余" + this.money);
                this.notifyAll();//取完之后唤醒其他线程
                this.wait();//自己等待,会释放锁
            } else {
                System.out.println(name + "取出失败!");
                this.wait();
            }
        }catch (InterruptedException e){
            e.printStackTrace();
        }
    }
//存
    public synchronized void inMoney(double money) {
        String name=Thread.currentThread().getName();
        System.out.println(name + " 取锁  *****");
        //
        try {
            if (this.money == 0) {
                System.out.print(name + "存钱 " + money+" - ");
                this.money += money;
                System.out.println(ID + "剩余" + this.money);
                this.notifyAll();
                this.wait();
            }
            else {
                System.out.println(name + "存入失败!");
                this.wait();
            }
        }catch (InterruptedException e){
            e.printStackTrace();
        }
    }
}
  • 两个线程类的实现继承Thread,在里面无限次存取操作

class getMoneyThread extends Thread{
    private account a;
    public getMoneyThread(account a,String name){
        super(name);
        this.a=a;
    }
    @Override
    public void run() {
        while (true) {
            a.getMoney(10000);
            try{
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

class inMoneyThread extends Thread{
    private account a;
    public inMoneyThread(account a,String name){
        super(name);
        this.a=a;
    }
    @Override
    public void run() {
        while (true) {
            a.inMoney(10000);
            try{
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
  • 创建账户对象和生产者消费者对象

/**
 * 多线程通信
 */
public class Demo_lock {
    public static void main(String[] args) {
        account acc=new account("happy",10000);
    //消费者
        new getMoneyThread(acc,"熊大").start();
        new getMoneyThread(acc,"熊二").start();
    //生产者
        new inMoneyThread(acc,"父亲").start();
        new inMoneyThread(acc,"母亲").start();
    }
}
  • 结果

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/385568.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

文科女生月入14k背后:转行IT软件测试不是谁都学得来!

转行软件测试背后,或许每个人都有自己的无奈。就拿今天要和大家分享的这位小姐姐来说吧,如果不是万不得已,又怎么会狠下心来转行到IT互联网? 应届生逃避就业,考研失败 和大多数人一样,小姐姐的大学生活过得…

SpringBoot入门 - 添加内存数据库H2

上文我们展示了通过学习经典的MVC分包结构展示了一个用户的增删查改项目,但是我们没有接入数据库;本文将在上文的基础上,增加一个H2内存数据库,并且通过Spring 提供的数据访问包JPA进行数据查询。准备知识点在介绍通过Spring JPA接…

专访华西二院吴邦华:隐私计算+AI全栈技术,构筑智慧医院建设的坚实数据底座|爱分析访谈

从IT时代步入DT时代,医疗大数据成为智慧医院建设的重要驱动力。经过多年信息化系统建设,很多医院已经积累了大量的医疗数据资源,但由于各业务系统间数据孤岛化严重、系统架构落后、数据缺乏深度治理等问题存在,导致现有数据深度及…

springsecurity中的类

Authentication AuthenticationProvider 每一个AuthenticationProvider对应一个Authentication 很多个AuthenticationProvider 由一个 ProviderManager管理 ProviderManager implements AuthenticationManager 一个ProviderManager有很多个 AuthenticationProvider Usern…

EasyPoi的excel模板预览与下载、导出简单/复杂数据

官方文档地址:easypoi官网,官方仅供参考,部分描述有问题 excel模板预览 准备工作 事先将整理好的excel模板存在项目中,如图 excel模板预览代码 GetMapping("excel")ApiOperation("excel预览")NoLogpubli…

多个关键字用or、and、包含、不包含动态拼接为正则表达式和SQL查询条件

目录前言校验思路1、存储方式2、实现图一实现图二实现结果最后前言 不知道大家有没有做过这种需求:在某字符串中,根据多个关键字去判断这串字符串是否满足条件。如下图: 亦或是 如果说要根据图二的关键字去数据库中查询符合条件的数据&a…

QT基础(18)- QAbstractSocket

QT基础(18)- QAbstractSocket1 创建简单的客户端2 QAbstractSocket2.1 简介2.2 枚举2.2.1 BingFlag2.2.2 NetworkLayerProtocol2.2.3 PauseMode2.2.4 SocketError2.2.5 SocketOption2.2.6 SocketType2.2.7 SocketState2.3 公有函数2.3.1 构造函数2.3.2 a…

文献阅读(47)—— 遗传数据研究近视和眼压与视网膜脱落的关系

文献阅读(47)—— 遗传数据研究近视和眼压与视网膜脱落的关系 文章目录文献阅读(47)—— 遗传数据研究近视和眼压与视网膜脱落的关系遗传数据研究近视和眼压与视网膜脱落的关系先验知识/知识拓展文章结构文章结果1. 视网膜脱落风险…

centos8安装docker运行java文件

本文由个人总结,如需转载使用请标明原著及原文地址 这里是基于我前一篇搭的centos8服务器做的,如果yum baseos源或appstream源有问题可以去看看前一篇 https://blog.csdn.net/qq_36911145/article/details/129263830 1.安装docker 1.1配置docker yum…

惠普战66pro如何选购内存条?一篇文章讲解清楚

笔记本:惠普 ZHAN66 PRO CPU:Intel Core™ i-8565U CPU 1.80GHz 内存条:Samsung PS: 如果有需要更换硬盘的可以看我之前发的文章,博主进行了长时间的测试。 硬盘选购长测评 文章目录前言一、内存是什么?二、如何操作呢…

错误:EfficientDet网络出现“No boxes to NMS“并且mAP:0.0的解决方案

近日,在使用谷歌新推出来的一个网络EfficientDet进行目标检测训练自己的数据集的时候,出现了如下错误: 其中项目开源地址是:https://github.com/toandaominh1997/EfficientDet.Pytorch 上面截图中的1和2代表我的类别名称。读者可…

【计算机二级python】综合题题目

计算机二级python真题 文章目录计算机二级python真题一、八十天环游世界二、八十天环游世界 问题一二、八十天环游世界 问题二一、八十天环游世界 附件中保存1个文本文件,分别对应2个问题‪‬‪‬‪‬‪‬‪‬‮‬‭‬‪‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‭‬‪‬‪‬…

315线上知识竞赛答题活动方案及模板分享

315线上知识竞赛答题活动方案及模板分享在315国际消费者权益日来临之际, 很多单位推出有奖知识竞答, 希望大家在了解专业知识的同时, 还可以拿到自己喜欢的奖品!这是消费者委员会和监管局联合举办的“315消费知识在线有奖竞答”活…

Springboot怎么集成Thymeleaf模板引擎?

Thymeleaf介绍Thymeleaf,是一个XML/XHTML/HTML模板引擎,开源的java库,可以用于SpingMVC项目中,用于代替JSP、FreeMarker或者其他的模板引擎;页面与数据分离,提高了开发效率,让代码重用更容易。S…

【JavaScript速成之路】JavaScript流程控制

📃个人主页:「小杨」的csdn博客 🔥系列专栏:【JavaScript速成之路】 🐳希望大家多多支持🥰一起进步呀! 文章目录前言1,流程控制2,分支结构2.1,if语句2.2&…

时机将至,名创优品或将再掀起一波消费热浪

北京时间2月28日,名创优品发布2023财年中报,财报显示,2023财年第二季度营收规模有所收窄,但净利润、毛利率、门店数量均实现了不错的增长,总体表现可圈可点。 (资料来源:富途牛牛) …

PIC单片机的快速代码生成和调试过程

1.相关工具说明:MCC ...................................Pic的代码模板软原始安装包:mcc-installer-5.2.2-windows.exeMPLAB X IDE ........................... 集成开发环境原始安装包:MPLABX-v6.00-windows-installer.exe编译环境&#x…

自动驾驶目标检测项目实战——基于深度学习框架yolov的交通标志检测

自动驾驶目标检测项目实战——基于深度学习框架yolov的交通标志检测 目前目标检测算法有很多,流行的就有faster-rnn和yolov,本文使用了几年前的yolov3框架进行训练,效果还是很好,当然也可以使用更高版本的Yolov进行实战。本代码使…

八股总结(一)C++语法、内存管理、新标准、STL

layout: post title: 八股总结(一)C语法、内存管理、新标准、STL description: 八股总结(一)C语法、内存管理、新标准、STL tag: C 文章目录基础语法语言特性面向对象的三大特性?C中新增了string,它与C语言…

Acwing---843. n-皇后问题

n-皇后问题1.题目2.基本思想3.代码实现1.题目 n−皇后问题是指将 n 个皇后放在 nn 的国际象棋棋盘上,使得皇后不能相互攻击到,即任意两个皇后都不能处于同一行、同一列或同一斜线上。 现在给定整数 n,请你输出所有的满足条件的棋子摆法。 …