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