内容简介:当多个线程同时共享,同一个全局变量或静态变量,做写的操作时,可能会发生数据冲突问题,也就是线程安全问题。但是做读操作是不会发生数据冲突问题结果:火车票会重复出售使用多线程之间同步synchronized或使用锁(lock)
当多个线程同时共享,同一个全局变量或静态变量,做写的操作时,可能会发生数据冲突问题,也就是线程安全问题。但是做读操作是不会发生数据冲突问题
模拟线程安全问题
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--; } } }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- Callable,阻塞队列,线程池问题
- 虚拟机线程问题分析(一):服务调优或问题排查执行方案
- Android子线程和更新UI问题
- 【Android多线程】哲学家就餐问题
- Hystrix系列之ThreadLocal跨线程传递问题
- 多线程Django程序耗尽数据库连接的问题
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
算法问题实战策略
[韩] 具宗万 / 崔盛一 / 人民邮电出版社 / 2015-2 / 119.00元
第一部分 开始解决问题 第二部分 算法分析 第三部分 算法设计范式 第四部分 一些著名的算法 第五部分 基本数据结构 第六部分 树 第七部分 图一起来看看 《算法问题实战策略》 这本书的介绍吧!