Android-多线程安全问题-synchronized

先看一个售票案例Demo,多线程程序对共享数据操做引起的安全问题:

package android.java.thread09;

/**
 * 售票线程
 */
class Booking implements Runnable {

    /**
     * 模拟票的总算 10张票
     */
    private int ticket = 10;

    @Override
    public void run() {

        while (true) {

            if (ticket > 0) {
                // 让线程在这里停一下,会更加容易复现线程的安全问题,就算不加这行代码,安全问题依然有
                try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); }

                System.out.println("名称:" + Thread.currentThread().getName() + "窗口卖出第" + ticket + "张票");
                ticket--;
            }

        }

    }
}

/**
 * 售票案例
 */
public class BookingTest {

    public static void main(String[] args) {

        /**
         * 定义Runnable实现类Booking,此实现类Booking不是线程,此实现类Booking给四个Thread去执行的
         */
        Runnable booking = new Booking();

        // 实例化线程对象
        Thread thread1 = new Thread(booking); // 此实现类Booking给Thread去执行的
        Thread thread2 = new Thread(booking); // 此实现类Booking给Thread去执行的
        Thread thread3 = new Thread(booking); // 此实现类Booking给Thread去执行的
        Thread thread4 = new Thread(booking); // 此实现类Booking给Thread去执行的

        // 开启启动线程
        thread1.start(); // 启动第Thread-0窗口 执行卖票任务
        thread2.start(); // 启动第Thread-1窗口 执行卖票任务
        thread3.start(); // 启动第Thread-2窗口 执行卖票任务
        thread4.start(); // 启动第Thread-3窗口 执行卖票任务


    }

}

 

打印的日志结果,注意:⚠️ 没有打印的日志结果都不一样,这是CPU对线程很是快速的切换形成的,哪一个线程先有执行权 就执行哪一个线程 都是随机的

名称:Thread-0窗口卖出第10张票
名称:Thread-3窗口卖出第9张票
名称:Thread-1窗口卖出第8张票
名称:Thread-2窗口卖出第7张票
名称:Thread-0窗口卖出第6张票
名称:Thread-3窗口卖出第5张票
名称:Thread-2窗口卖出第4张票
名称:Thread-1窗口卖出第4张票
名称:Thread-2窗口卖出第2张票
名称:Thread-0窗口卖出第1张票
名称:Thread-3窗口卖出第1张票
名称:Thread-1窗口卖出第-1张票
名称:Thread-2窗口卖出第-2张票java

 

CPU的随机性,到底切换到哪一个线程,到底执行哪一个线程代码的多少行,等等,都是随机的android

 

 

分析缘由,为何会出现以上日志打印的各个状况呢,为何会出现 0张票 -1张票   这种状况呢?,看如下CPU执行线程的随机性就明白了

 


 

 

经过以上画图分析缘由,形成安全问题的有如下两个因素: 

  1.线程任务中,发现有共享数据,例如:ticket。安全

  2.多线程操做共享数据,例如:ticket。多线程

形成的缘由是:Thread-0在对共享数据操做过程当中,CPU执行了Thread-1对共享数据操做,   至关于:我在数钱,忽然我出去有事了,而后有我的拿了500块钱,等我在回来数钱的时候,就已经发生是数据安全问题ide

 


 

 

 

解决多线程安全问题,synchronize 加同步代码块,同步代码块:synchronize{ 操做共享数据的代码 }

 

 

package android.java.thread09;

/**
 * 售票线程
 */
class Booking implements Runnable {

    /**
     * 模拟票的总算 10张票
     */
    private int ticket = 10;

    @Override
    public void run() {

        while (true) {

            /**
             * 加入了同步代码块的代码synchronized,
             * 无论CPU如何疯狂的切换执行,
             * 只要同步代码块里面的代码没有执行完,
             * 就不许其余线程进来执行
             * 这样就保证了多线程操做共享数据的安全新
             */
            synchronized (Booking.class) { // 同步操做共享数据的代码

                if (ticket > 0) {

                    // 让线程在这里停一下,会更加容易复现线程的安全问题,就算不加这行代码,安全问题依然有
                    try {
                        Thread.sleep(200);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                    System.out.println("名称:" + Thread.currentThread().getName() + "窗口卖出第" + ticket + "张票");
                    ticket--;
                }
            }

        }

    }
}

/**
 * 售票案例
 */
public class BookingTest {

    public static void main(String[] args) {

        /**
         * 定义Runnable实现类Booking,此实现类Booking不是线程,此实现类Booking给四个Thread去执行的
         */
        Runnable booking = new Booking();

        // 实例化线程对象
        Thread thread1 = new Thread(booking); // 此实现类Booking给Thread去执行的
        Thread thread2 = new Thread(booking); // 此实现类Booking给Thread去执行的
        Thread thread3 = new Thread(booking); // 此实现类Booking给Thread去执行的
        Thread thread4 = new Thread(booking); // 此实现类Booking给Thread去执行的

        // 开启启动线程
        thread1.start(); // 启动第Thread-0窗口 执行卖票任务
        thread2.start(); // 启动第Thread-1窗口 执行卖票任务
        thread3.start(); // 启动第Thread-2窗口 执行卖票任务
        thread4.start(); // 启动第Thread-3窗口 执行卖票任务


    }

}

如下日志结果,是CPU随机执行到哪一个线程,就哪一个线程打印,CPU执行线程的随机性很重要

如下日志结果,是CPU随机执行到哪一个线程,就哪一个线程打印,CPU执行线程的随机性很重要

如下日志结果,是CPU随机执行到哪一个线程,就哪一个线程打印,CPU执行线程的随机性很重要

 

.........spa

相关文章
相关标签/搜索