当多个线程同时共享同一全局变量或静态变量时,在做读操作时不会发送数据冲突,而在做写操作时可能会发送数据冲突问题,就会出现线程安全问题。
背景: 某工厂需拖运100T货物,找了3家托运公司,用多线程模拟托运情况。
代码如下:
/** * @author MuXin * @date 2020/10/21 16:11 * * 某工厂需拖运100T货物,找了3家托运公司,用多线程模拟托运情况。 */ public class ThreadDemo { public static void main(String[] args) { ThreadGoods threadGoods = new ThreadGoods(); Thread threadA = new Thread(threadGoods, "A公司"); Thread threadB = new Thread(threadGoods, "B公司"); Thread threadC = new Thread(threadGoods, "C公司"); threadA.start(); threadB.start(); threadC.start(); } static class ThreadGoods implements Runnable { //货物总量 private int goods = 100; @Override public void run() { while (goods > 0) { try { //等待0.1s Thread.sleep(100); } catch (Exception e) { } //执行运货操作 System.out.println(Thread.currentThread().getName()+",搬运第"+(101-goods)+"T货物"); goods--; } } } }输出结果: 当多个线程共享同一个全局成员变量时,做写的操作可能会发生数据冲突问题。
将可能出现问题的代码块包裹起来。
/** * @author MuXin * @date 2020/10/21 16:11 * <p> * 某工厂需拖运100T货物,找了3家托运公司,用多线程模拟托运情况。 */ public class ThreadDemo { public static void main(String[] args) { ThreadGoods threadGoods = new ThreadGoods(); Thread threadA = new Thread(threadGoods, "A公司"); Thread threadB = new Thread(threadGoods, "B公司"); Thread threadC = new Thread(threadGoods, "C公司"); threadA.start(); threadB.start(); threadC.start(); } static class ThreadGoods implements Runnable { //自定义多线程同步锁 private Object mutex = new Object(); //货物总量 private int goods = 100; @Override public void run() { while (goods > 0) { try { //等待0.1s Thread.sleep(100); } catch (Exception e) { } synchronized (mutex) { if(goods > 0) { try { //等待0.1s Thread.sleep(100); } catch (Exception e) { } //执行运货操作 System.out.println(Thread.currentThread().getName() + ",搬运第" + (101 - goods) + "T货物"); goods--; } } } } } }运行结果:
在方法上修饰synchronized称为同步函数; synchronized使用的锁是this锁。
/** * @author MuXin * @date 2020/10/21 16:11 * <p> * 某工厂需拖运100T货物,找了3家托运公司,用多线程模拟托运情况。 */ public class ThreadGoods implements Runnable { //货物总量 private int goods = 100; //自定义多线程同步锁 private Object mutex = new Object(); @Override public void run() { while (goods > 0) { try { //等待0.1s Thread.sleep(100); } catch (Exception e) { } moveGoods(); } } public synchronized void moveGoods() { if (goods > 0) { try { //等待0.1s Thread.sleep(100); } catch (Exception e) { } //执行运货操作 System.out.println(Thread.currentThread().getName() + ",搬运第" + (101 - goods) + "T货物"); goods--; } } }执行结果:
在方法上加static关键字,使用synchronized关键词修饰,或者使用类.class文件; 静态同步函数使用的锁是该函数所属字节码文件对象。
/** * @author MuXin * @date 2020/10/21 16:11 * <p> * 某工厂需拖运100T货物,找了3家托运公司,用多线程模拟托运情况。 */ public class ThreadGoods implements Runnable { //货物总量 private int goods = 100; //自定义多线程同步锁 private Object mutex = new Object(); @Override public void run() { while (goods > 0) { try { //等待0.1s Thread.sleep(100); } catch (Exception e) { } moveGoods(); } } public void moveGoods() { synchronized (ThreadGoods.class) { if (goods > 0) { try { //等待0.1s Thread.sleep(100); } catch (Exception e) { } //执行运货操作 System.out.println(Thread.currentThread().getName() + ",搬运第" + (101 - goods) + "T货物"); goods--; } } } }执行结果: