• 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 的公共对象 来定义同步锁

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

  • 相关阅读:
    Kotlin高仿微信-第37篇-拍照
    Leetcode.2522 将字符串分割成值不超过 K 的子字符串
    生物神经网络 原理分析研读01
    AI AIgents时代 - (四.) HuggingGPT & MetaGPT
    第2-4-7章 docker安装WorkBench-规则引擎Drools-业务规则管理系统-组件化-中台
    day 2 2.3.2 类和对象
    EM@三角恒等变换P1
    Linux网络编程---Socket编程
    MCE | 世界“第一杀手”——心血管疾病
    【软考笔记】(二)程序设计语言
  • 原文地址:https://blog.csdn.net/weixin_45966674/article/details/128050503