线程安全的三种解决方式

线程安全

产生线程安全问题的三个条件

1.多个线程
2.多条语句操作共享语句
3.修改共享数据的代码

多线程中可能出现的问题

三个线程共享一个数据时,会产生的问题,买票会多卖一张

public static void main(String[] args) throws InterruptedException {
        B b1 = new B();
        Thread a1 = new Thread(b1, "wei1");
        Thread a2 = new Thread(b1, "wei2");
        Thread a3 = new Thread(b1, "wei3");
        a1.start();
        a2.start();
        a3.start();

    }
    class B implements Runnable {
    static int Piao = 100;
    int t = 0;
    public B() {
    }
    public B(int piao) {
        Piao = piao;
    }
    @Override
    public void run() {
        while (true) {
            if (Piao <= 0) break;
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
            }
            System.out.printf("%S : 卖出 %d座 的票,剩余票%d张\n ", Thread.currentThread().getName(), (t++), Piao--);
        }
        System.out.println(Thread.currentThread().getName() + " 线程结束!");
    }
}

在这里插入图片描述

1.同步代码块解决线程安全

重写的run方法加上对象锁(此处的锁对象为同一个锁,不能是新对象)

 @Override
    public void run() {
        while (true) {
            synchronized (this) {
                if (Piao <= 0) break;
                System.out.printf("%S : 卖出 %d座 的票,剩余票%d张\n ", Thread.currentThread().getName(), (t++), Piao--);

                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                }
            }
        }
        System.out.println(Thread.currentThread().getName() + " 线程结束!");
    }

在这里插入图片描述

2.同步方法

原理

在这里插入图片描述

因为每次创建新的实例所以需要采用静态方法调用类名.class作为锁对象。

 @Override
    public void run() {
        while (true) {
            if (Piao <= 0) break;
            sall();
        }
    }

    public static synchronized void sall() {
        if (Piao <= 0)return;
        System.out.printf("%S : 卖出 %d座 的票,剩余票%d张\n ", Thread.currentThread().getName(), (t++), --Piao);
        try {
            Thread.sleep(10);
        } catch (InterruptedException e) {
        }
    }

在这里插入图片描述

3.Lock锁

锁上之后一定要记得开锁

在这里插入图片描述

 @Override
    public void run() {
        while (true) {
            lock.lock();
                if (Piao <= 0) break;
                System.out.printf("%S : 卖出 %d座 的票,剩余票%d张\n ", Thread.currentThread().getName(), (t++), --Piao);
            lock.unlock();
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {

            }
        }
        System.out.println(Thread.currentThread().getName() + " 线程结束!");
    }

在这里插入图片描述

但是程序本身并没有运行结束(因为当最后一次锁上之后票为0会跳出循环)

需要添加try/finally (ctrl + alt + t )
在这里插入图片描述

注: 三种代码原理基本类似,都是将代码块锁住等待执行完毕下一个进程继续进行

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值