美文网首页
线程安全

线程安全

作者: LiuXiaozhang | 来源:发表于2019-07-30 15:48 被阅读0次

1.线程安全产生的原因

如果有多个线程在同时运行,而这些线程可能会同时运行这段代码。
程序每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的。

以电影院卖票为例演示线程安全问题
由三个不同的渠道同时卖100张票

线程任务:

public class MyRunnable implements Runnable {

    // 卖电影票(共享数据)
    private int ticket = 100;
    public void run() {
        while (true) {
            if (ticket > 0) {
                try {
                    Thread.sleep(50);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + "出售第" + ticket-- + "张票");
            }
        }

    }
}



public static void main(String[] args) {
        //创建线程任务
        MyRunnable mr = new MyRunnable();
        //创建线程
        Thread t0 = new Thread(mr);
        Thread t1 = new Thread(mr);
        Thread t2 = new Thread(mr);
        //执行线程
        t0.start();
        t1.start();
        t2.start();
        
    }

此时执行代码会发现会出现卖第0张和-1张票或者重复卖同一张票的情况,

原因是某个时间多个线程都执行了同一段if语句中的代码,使得全局变量ticket不准确(操作的票可能被另一个线程卖掉了)

所以解决这个问题需要在一个线程在执行线程任务时,其他线程不能执行;这也就变得和单线程一样了。

解决方法:
(1)同步代码块

public class MyRunnable implements Runnable {

    // 卖电影票(共享数据)
    private int ticket = 100;
    private Object obj = new Object();// 保证锁对象的唯一性

    public void run() {

        while (true) {
            synchronized (obj) {
                if (ticket > 0) {
                    try {
                        Thread.sleep(50);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + "出售第" + ticket-- + "张票");
                }
            }

        }

    }

}

注意:用synchronized(锁对象){}时, 锁对象要设为全局变量保证其唯一性;

(2)同步方法


public class MyRunnable2 implements Runnable {

    // 卖电影票(共享数据)
    private int ticket = 100;
    public void run() {

        while (true) {
            sale();

        }

    }
    public synchronized void sale() {
        // 隐含的锁 this
        if (ticket > 0) {
            try {
                Thread.sleep(50);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + "出售第" + ticket-- + "张票");
        }

    }

}

注意:将同步代码块封装成一个方法并用synchronized 修饰,这里不需要指定锁对象,这里的锁对象默认为本类对象this
若果是静态同步方法: 在方法声明上加上static synchronized

public static synchronized void method(){

可能会产生线程安全问题的代码

}

静态同步方法中的锁对象是 类名.class

(3)使用lock接口

public class MyRunnable2 implements Runnable {

    // 卖电影票(共享数据)
    private int ticket = 100;
    private Lock lock = new ReentrantLock();//创建锁对象

    public void run() {

        while (true) {
            lock.lock();
            if (ticket > 0) {
                try {
                    Thread.sleep(50);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + "出售第" + ticket-- + "张票");
            }

            lock.unlock();
        }
    }
}

其实和同步代码块差不多 ,在创建所对象时用Lock接口的子类创建,用lock()和unlock()方法将可能出现安全的代码包起来 锁的释放可以手动控制

相关文章

  • atomic & nonatomic

    什么是线程安全??? 线程安全:多线程操作共享数据不会出现想不到的结果就是线程安全的,否则,是线程不安全的。 at...

  • ConcurrentHashMap源码设计分析

    二、线程安全(Thread-safe)的集合对象:● Vector 线程安全● HashTable 线程安全● S...

  • HashMap 和 Hashtable 的区别

    线程安全: HashMap 是非线程安全的,而 Hashtable 是线程安全的,因为 Hashtable 内部的...

  • Java 的 StringBuffer 和 StringBuil

    区别就是:线程安全,StringBuffer 是线程安全的,StringBuilder 不是线程安全的。 他俩的实...

  • Java单例模式,线程安全

    懒汉式:线程安全,开销大 双重检查锁:线程安全,根据需求使用 静态内部类锁:线程安全,比较推荐 饿汗式:线程安全,...

  • 2018-06-12 第三十七天

    一、线程安全 线程安全的问题,是针对多线程的程序。单线程的情况下,是不存在线程安全问题。 产生线程安全问题的原因:...

  • 线程安全知多少

    1. 如何定义线程安全 线程安全,拆开来看: 线程:指多线程的应用场景下。 安全:指数据安全。 多线程就不用过多介...

  • JAVA 线程安全

    线程安全定义 一个类在可以被多个线程安全调用时就是线程安全的。 线程安全分类 线程安全不是一个非真即假的命题,可以...

  • synchronized锁

    一、线程安全的概念与synchronized 1、线程安全概念 并发程序开发的一大关注重点就是线程安全,线程安全就...

  • 线程安全的NSMutableDictionary

    NSDictionary是线程安全的,NSMutableDictionary是线程不安全的。利用锁来保证线程的安全...

网友评论

      本文标题:线程安全

      本文链接:https://www.haomeiwen.com/subject/aysnrctx.html