线程安全问题

如何判断一个程序是否存在线程不安全的现象呢?

三要素(同时满足):
1、是否存在多线程环境?
2、是否存在共享数据?
3、是否存在多条语句操作着共享数据?

举例:电影院卖票程序

a. 有重复售卖同一张票的情况(原因1)
b. 还出现了一个不该出现的票数据,比如第0张票,第-1张票(原因2)

原因:

  1. cpu小小的时间片,足以让程序执行很多次
  2. 线程的执行具有随机性,且是抢占式执行的

如何解决线程不安全的现象?

1、加入同步代码块
synchronized(对象){
操作共享数据的代码
}
这里的对象,可以是任意一个new出来的对象,但是要保证多个线程之间是同一个对象。

class Window implements Runnable{
    private static int tickets = 100;
    private Object object = new Object();
    @Override
    public void run() {
        while (true){
            synchronized (object){
                if(tickets>0){
                    try {
                        Thread.sleep(50);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName()+" 正在出售第 "+(tickets--)+" 张票......");
                }
            }
        }
    }
}

synchronized的使用
1、同步代码块 - 锁对象 - 任意一个对象,前提是多个线程对象共享一个
synchronized (object)
2、同步方法 - 锁对象 - this
public synchronized void sellTicket()
3、同静态方法 - 锁对象 - 当前类的class文件对象
synchronized (Window.class)
2.lock锁
利用ReentrantLock类创建锁对象,要求多个线程对象共享一个,不需要考虑锁对象是谁了。

class Window implements Runnable {
    private static int tickets = 100;
    private ReentrantLock lock = new ReentrantLock();
    @Override
    public void run() {
        while (true) {
            lock.lock(); // 加锁
            if (tickets > 0) {
                try {
                    Thread.sleep(50);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + " 正在出售第 " + (tickets--) + " 张票......");
            }
            lock.unlock(); // 解锁
        }
    }
}
posted @   hello_future  阅读(12)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
点击右上角即可分享
微信分享提示