当多个线程同时共享,同一个全局变量或静态变量,做写的操作时,可能会发生数据冲突问题,也就是线程安全问题。但是做读操作是不会发生数据冲突问题

模拟线程安全问题

public class SafeThread implements Runnable {    private int ticketCount = 50;    @Override    public void run() {        while (ticketCount > 0) {            try {                Thread.sleep(50);            } catch (InterruptedException e) {                e.printStackTrace();            }            System.out.println(Thread.currentThread().getName() + ",出售第" + (50 - ticketCount + 1) + "张票");            ticketCount--;        }    }}
@RequestMapping("test-safe")    public void testSafe() {        SafeThread safeThread = new SafeThread();        Thread t1 = new Thread(safeThread, "thread-1");        Thread t2 = new Thread(safeThread, "thread-2");        t1.start();        t2.start();    }

结果:火车票会重复出售

解决办法

使用多线程之间同步synchronized或使用锁(lock)
1.同步代码块

public class SafeThread implements Runnable {    private int ticketCount = 50;    @Override    public void run() {        while (ticketCount > 0) {            try {                Thread.sleep(50);            } catch (InterruptedException e) {                e.printStackTrace();            }            synchronized (this) {                System.out.println(Thread.currentThread().getName() + ",出售第" + (50 - ticketCount + 1) + "张票");                ticketCount--;            }        }    }}

2.同步方法

public class SafeThread implements Runnable {    private int ticketCount = 50;    @Override    public void run() {        while (ticketCount > 0) {            try {                Thread.sleep(50);            } catch (InterruptedException e) {                e.printStackTrace();            }//            synchronized (this) {//                System.out.println(Thread.currentThread().getName() + ",出售第" + (50 - ticketCount + 1) + "张票");//                ticketCount--;//            }            sale();        }    }    private synchronized void sale() {        System.out.println(Thread.currentThread().getName() + ",出售第" + (50 - ticketCount + 1) + "张票");        ticketCount--;    }}

注意:同步函数使用this锁

3.静态同步函数
方法上加上static关键字,使用synchronized 关键字修饰或者使用类.class文件。
静态的同步函数使用的锁是该函数所属字节码文件对象
可以用 getClass方法获取,也可以用当前类名.class 表示

public class SafeThread implements Runnable {    private int ticketCount = 50;    @Override    public void run() {        while (ticketCount > 0) {            try {                Thread.sleep(50);            } catch (InterruptedException e) {                e.printStackTrace();            }//            synchronized (this) {//                System.out.println(Thread.currentThread().getName() + ",出售第" + (50 - ticketCount + 1) + "张票");//                ticketCount--;//            }//            sale();            sale2();        }    }    private synchronized void sale() {        System.out.println(Thread.currentThread().getName() + ",出售第" + (50 - ticketCount + 1) + "张票");        ticketCount--;    }    private void sale2() {        synchronized (SafeThread.class) {            System.out.println(Thread.currentThread().getName() + ",出售第" + (50 - ticketCount + 1) + "张票");            ticketCount--;        }    }}