【java】java中解决线程安全问题的三种方法

2023-11-09

java中解决线程安全问题的三种方法

当我们使用线程进行卖票时会出现诸多的安全问题为了解决这种情况,有三种方法可以进行选择
第一种是同步代码块
第二种是同步方法
第三种是Lock锁

在没有用的解决安全问题的时候会出现以下问题

测试类

public class demotest {
    public static void main(String[] args) {
        MyRunnable myRunnable01 = new MyRunnable();
        new Thread(myRunnable01,"张三").start();
        new Thread(myRunnable01,"李四").start();
        new Thread(myRunnable01,"王五").start();
//        new Thread(myRunnable01).start();
    }
}

Runnable接口的实现类

public class MyRunnable implements Runnable {
    private int ticket=100;
    Object object=new Object();
    @Override
    public void run() {
        while (true){
            if (ticket>0){
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName()+"--->正在卖第"+(101-ticket)+"张票");
                ticket--;
            }else {
                System.out.println("对不起,票已售光!");
                break;
            }
        }
    }
}

输出

张三--->正在卖第1张票
王五--->正在卖第1张票
李四--->正在卖第1张票
王五--->正在卖第4张票
张三--->正在卖第4张票
李四--->正在卖第6张票
王五--->正在卖第7张票

发现会出现售卖同一张票的情况,这是因为在cpu进行多线程选择时,他们已经进入了run()方法进行了if语句的判断,所以在if语句之后的ticket- -并不能影响已经输出的语句。
这里就需要用到同步的概念了,学过操作系统的应该会很熟悉。

第一种方法:同步代码块

同步代码块 : synchronized 关键字可以用于方法中的某个区块中,表示只对这个区块的资源实行互斥访问。
格式:

synchronized(同步锁){
     需要同步操作的代码
}

同步锁:
对象的同步锁只是一个概念,可以想象为在对象上标记了一个锁.

  1. 锁对象 可以是任意类型。
  2. 多个线程对象 要使用同一把锁。

实例:Runnable接口实现类

    private int ticket=100;
    Object object=new Object();定义锁对象
    @Override
    public void run() {
        while (true){
        synchronized (object){
            if (ticket>0){
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName()+"--->正在卖第"+(101-ticket)+"张票");
                ticket--;
            }else {
                System.out.println("对不起,票已售光!");
                break;
            }
        }
    }}
}

输出

张三--->正在卖第1张票
张三--->正在卖第2张票
王五--->正在卖第3张票
王五--->正在卖第4张票
王五--->正在卖第5张票
王五--->正在卖第6张票
王五--->正在卖第7张票

在这里可以看到输出的结果很正常

第二种方法:同步方法

同步方法 :使用synchronized修饰的方法,就叫做同步方法,保证A线程执行该方法的时候,其他线程只能在方法外等着。
格式:

public synchronized void method(){
   可能会产生线程安全问题的代码 
}

同步锁是谁?
对于非static方法,同步锁就是this。
对于static方法,我们使用当前方法所在类的字节码对象(类名.class)。
使用步骤:
1.把访问了共享数据的代码抽取出来,放到一个方法中
2.在方法上添加synchronized修饰符
案例Runnable的实现类

public class MyRunnable implements Runnable {
    private int ticket=100;
    @Override
    public void run() {
        while (true){
            method();
        }
    }
        public synchronized void method(){
                if (ticket>0){
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName()+"--->正在卖第"+(101-ticket)+"张票");
                    ticket--;
                }
        }
}

重新定义一个带有synchronized修饰符的方法将需要进行同步的代码给框起来,之后再run方法中在进行调用方法即可。

第三种方法:Lock锁

java.util.concurrent.locks.Lock 机制提供了比synchronized代码块和synchronized方法更广泛的锁定操作,
同步代码块/同步方法具有的功能Lock都有,除此之外更强大,更体现面向对象。
Lock锁也称同步锁,加锁与释放锁方法化了,如下:
public void lock() :加同步锁。
public void unlock() :释放同步锁。
使用步骤:
1.在成员位置创建一个ReentrantLock对象。
2.在可能会出现安全问题的代码前调用Lock接口中的方法Lock获取锁。
3.在可能会出现安全问题的代码后调用Lock接口中的方法unLock释放锁。
案例Runnable的实现类

public class MyRunnable implements Runnable {
    private int ticket=100;
    Lock l=new ReentrantLock();
    @Override
    public void run() {
        while (true){
            l.lock();//加同步锁
            if (ticket>0){
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName()+"--->正在卖第"+(101-ticket)+"张票");
                ticket--;
            }else {
                System.out.println("对不起,票已售光!");
                break;
            }
            l.unlock();//释放锁
        }
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【java】java中解决线程安全问题的三种方法 的相关文章

随机推荐

  • 浮点类型四则运算

    eval用于把字符串转化为数值 int是转化为整数 float是转化为小数 试编程实现分两行输入两个非零浮点数 并在4 行中按顺序输出两个数的加 减 乘 除的计算式和计算结果 计算结果str format 方法保留小数点后3位数字 要求输出
  • 【已解决】span插入button插槽中想要点击不生效

    span插入button插槽中 发现点击span文字也回弹出button的事件 解决方案 click stop span test span
  • TX2入门(9)——yolov3(1)

    1 从github上clone git clone https github com pjreddie darknetcd darknet 2 修改Makefile 以下注释来自参考链接1 GPU 1 是否需要用GPU CUDNN 1 是否
  • Docker按装ElasticSearch

    1 检查自己的虚拟机是否安装了Docker环境 2 拉去镜像 依次执行下面两个命令 拉取两个相关镜像 存储和检索数据 docker pull elasticsearch 7 4 2 可视化检索数据 docker pull kibana 7
  • 如何使用 Python Selenium 自动购买 Interpark 演唱会门票?

    前言 Interpark是韩国的一家知名网上购物网站 成立于1996年 它是韩国最早开展网上零售业务的公司之一 提供各种产品 包括各种书籍 电子产品 珠宝 户外用品 食品和服装等等 Interpark还提供机票 旅游和酒店等服务 它已经成为
  • 什么是Redis持久化

    Redis持久化简单概括为两点 RDB Redis DataBase AOF Append Only File 下面解释这两点 RDB相关知识 RDB是在指定的时间间隔内将内存中的数据集快照写入磁盘 也就是行话将的Snapshot快照 它恢
  • 使用 ArrayList 应当避免的坑

    大家都知道 ArrayList 是由数组实现 而数据的长度有限 需要在合适的时机对数组扩容 当我们初始化一个长度为 2 的 ArrayList 并往里边写入三条数据时 ArrayList 就得扩容了 也就是将之前的数据复制一份到新的数组长度
  • clion的学习资料

    1 官方指南 https www jetbrains com help clion meet clion html 2 下面是一些快捷键的例子 快捷键配置 File gt Setting gt Keymap gt Keymaps 选择Vis
  • 一文读懂USB Type-C接口 <一>:引脚和功能指南

    本文将介绍USB Type C标准的一些最重要的特性 你知道如何使用USB Type C接口吗 本文列出了USB Type C引脚的解剖结构 并简要介绍了其各种模式 USB Type C是一种USB连接器系统的规范 它在智能手机和移动设备中
  • 基于单片机的蔬菜大棚温湿度智能控制系统设计

    基于单片机的蔬菜大棚温湿度智能控制系统设计 目 录 基于单片机的蔬菜大棚温湿度智能控制系统设计 1 设计背景 2 设计方案 2 1 设计目的 2 2 设计思路 2 3 系统整体设计思路 2 4 设计要求 3 功能模块设计 3 1 主控模块
  • zynq audio pcm DMA

    本篇接着上一篇 概述pcm调用DMA操作流程 接着ynq alsa说起 181 static int axi i2s probe struct platform device pdev 182 183 struct resource res
  • 浅谈【Stable-Diffusion WEBUI】(AI绘图)的基础和使用

    文章目录 零 AI绘图 一 简单介绍 1 1 Stable Diffusion 1 2 Stable Diffusion WEB UI 1 3 SD WebUI启动器和整合包 二 使用 2 1 启动 控制台 WEBUI 2 2 模型 2 2
  • How to change SSH port on Centos 6, 7, and 8.

    In this tutorial we will go through the steps on how to change the SSH port on Centos 6 7 and 8 Download PDF Posted 23 S
  • 解决vue白屏问题

    咱们先看看vue白屏在ios手机上是如何产生的 首页跳转到到第二屏 再从二级页面返回到首页就会出现白屏情况 解决思路 既然是首页白屏那么就要从首页开始解决问题 经过多次比对发现 返回到首页后 出现白屏 然后咱们用手触摸或则向下滑动 白屏就没
  • opencv编写均值滤波_opencv3.2.0图像处理之均值滤波blur API函数

    均值滤波 blur函数 函数原型 void blur InputArray src OutArray dst Size ksize Point anchor point int borderType BORDER DEFAULT 参数详解同
  • 仿叮咚买菜开源代码

    1 预览 1 前台 http dingdong nodebook top github地址 https github com cgq001 dingdong 2 后台管理 http dingdong admin nodebook top g
  • Python 中的列表推导式

    Python 中的列表推导式 简单用法 添加多个条件 多个列表使用 替换 Reduce 和 Lambda 嵌套列表推导式 列表推导式是一种 Python 构造 可减少生成新列表或过滤现有列表所需的代码行 列表推导式包含在方括号内 它由一个表
  • 12306查询车票信息返回的数据解析

    例如普通k 返回的车次信息 26000K772633 K7727 HDP QTP BXP TJP 00 42 02 33 01 51 Y UqBhHc2N4C1b00y5vYeRuG025cKMjh0sxUwHbuwDNWuOXRhule
  • shell case语句及函数

    case 菜单选择打印 语法 case var in var变量 patten 1 匹配模式1 a b c 和or类似 command 需要执行的命令 命令执行完毕 patten 2 command 默认值 没有匹配的模式 command
  • 【java】java中解决线程安全问题的三种方法

    java中解决线程安全问题的三种方法 当我们使用线程进行卖票时会出现诸多的安全问题为了解决这种情况 有三种方法可以进行选择 第一种是同步代码块 第二种是同步方法 第三种是Lock锁 在没有用的解决安全问题的时候会出现以下问题 测试类 pub