线程安全

运行代码:

 public static void main(String[] args) {
        SellTicket st = new SellTicket();

        Thread t1 = new Thread(st,"窗口1");
        Thread t2 = new Thread(st,"窗口2");
        Thread t3 = new Thread(st,"窗口3");
        //启动线程
        t1.start();
        t2.start();
        t3.start();
    }

Demo1:

package course;

/**
 * 买票窗口
 */
public class SellTicket implements Runnable {
    private int tickets = 10;
    @Override
    public void run() {
        int sum = 10;
        while (true){
            if (tickets > 0) {
                tickets--;
                System.out.println(Thread.currentThread().getName() + "正在出售第" + (sum - tickets) + "张票");
            }
        }
    }
}

线程安全1.png

线程安全问题
运行以上代码,3个售票窗口售卖10张票会出现超卖或少卖的情况
为什么会出现问题?(这也是我们判断多线程程序是否会有数据安全问题的标准)

  1. 是否是多线程环境
  2. 是否有共享数据
  3. 是否有多条语句操作共享数据

如何解决多线程按问题?

  • 让程序没有安全问题的环境
  • 实现方式:把多条语句操作共享数据的代码给锁起来,让任意时刻只能有一个线程执行即可

解决方法:

  1. 同步代码块:锁多条语句操作共享数据,可以使用同步代码块
    格式:
    synchronized(任意对象){

     多条语句操作共享数据的代码

    }

  2. 通过Lock类

Demo2(修改Demo1,使用synchronized关键字):

package course;

/**
 * 买票窗口
 */
public class SellTicket implements Runnable {
    private int tickets = 10;
    //使用同步代码块
    private Object obj = new Object();

    @Override
    public void run() {
        int sum = 10;
        synchronized (obj) {
            while (true) {
                if (tickets > 0) {
                    tickets--;
                    System.out.println(Thread.currentThread().getName() + "正在出售第" +(sum - tickets)+ "张票");
                }
            }
        }
    }
}

线程安全2.png

Demo3(修改Demo2,使用Lock类):

package course;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 买票窗口
 */
public class SellTicket implements Runnable {
    private int tickets = 10;
    //使用Lock  通过Lock的实现类
    private Lock lock = new ReentrantLock();


    @Override
    public void run() {
        int sum = 10;
        while (true) {
            lock.lock();
            if (tickets > 0) {
                tickets--;
                System.out.println(Thread.currentThread().getName() + "正在出售第" +(sum - tickets)+ "张票");

            }

            lock.unlock();
        }
    }
}

线程安全3.png

添加新评论