• java 同步锁synchronized 解决线程共享数据重复操作问题


    我们先来写一个买票程序
    我们先创建一个包 在包下创建两个类

    customException 线程类 负责编写抢票的主要逻辑
    参考代码如下

    public class customException implements Runnable {
        private int tickets = 100;
    
        public void run () {
            while (tickets > 0){
                if(tickets > 0) {
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName()+"正在出售第"+tickets+"张票");
                    tickets--;
                }
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    text 测试类 用于实例化线程对象 并执行线程

    public class text {
        public static void main(String args[]) {
            Runnable Runnable = new customException();
            Thread m1 = new Thread(Runnable,"客户");
            Thread m2 = new Thread(Runnable,"黄牛");
            Thread m3 = new Thread(Runnable,"导爷");
            m1.start();
            m2.start();
            m3.start();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    然后 我们运行代码
    在这里插入图片描述
    我们会发现 第一百张票被抢了三次

    在这里插入图片描述
    负一也出来啦 这就是我们要解决的问题 线程执行随机性导致同一张票出售多次

    科普个知识

    java有特意为此现象 定义了数据安全性的描述
    在这里插入图片描述
    那么 显然 我们不是一个单线程 而是多线程 第一条 我们是到达了不安全的条件的
    我们有一个tickets共享数据 所以 第二个条件 我们也是达到了不安全条件的

    第三个 我们确实是在线程中 操作了 tickets 共享数据 tickets –

    所以 这三个条件我们都达到了不安全的条件

    java提供了 synchronized 锁方法解决这个问题 接受一个对象参数
    这里 我们将customException 的 run方法修改代码如下

    public void run () {
       while (tickets > 0){
            synchronized (new Object()) {
                if(tickets > 0) {
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName()+"正在出售第"+tickets+"张票");
                    tickets--;
                }
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    此时 我们调用了synchronized 将操作公共数据的代码锁了起来 运行结果如下

    在这里插入图片描述
    但很明显 问题并没有解决 因为我们传递对象是在方法中定义的 每个线程进来 看到的锁都是不一样的

    那么 我们可以写一个公共的对象来锁

    customException类代码修改如下

    public class customException implements Runnable {
        private int tickets = 100;
        private Object obj = new Object();
    
       public void run () {
            while (true){
                synchronized (obj) {
                    if(tickets > 0) {
                        try {
                            Thread.sleep(100);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        System.out.println(Thread.currentThread().getName()+"正在出售第"+tickets+"张票");
                        tickets--;
                    }
                }
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    这里我们直接定义了一个叫 obj 的公共对象 来定义同步锁

    然后我们执行代码
    在这里插入图片描述
    在这里插入图片描述
    可以看到 我们的数据已经是正常的执行了 这就解决了我们上述的问题

  • 相关阅读:
    安防监控系统/视频云存储/视频AI智能分析:人形检测算法应用汇总
    Mysql---三张表(student,课程,分数) 查询课程为数学的学生姓名,编号,成绩
    基于SSM的金鱼销售平台
    RuoYi-Vue-Plus 高端进阶 源码分析 系列教程
    linux 学习 day08 多线程
    论文《Link Prediction on Latent Heterogeneous Graphs》阅读
    Python全栈开发【基础-06】垃圾回收机制
    【MATLAB源码-第52期】基于matlab的4用户DS-CDMA误码率仿真,对比不同信道以及不同扩频码。
    【外汇天眼】价格波动的节奏感:优化止盈方法!
    开坑:关于MATLAB 使用CNN进行图像分类时,训练输出的验证集精度会陡降的问题
  • 原文地址:https://blog.csdn.net/weixin_45966674/article/details/128050503