给出一个问题,如下:

解决方案如下:

  1. public class Demo_5 {
  2.  
  3. public static void main(String[] args) {
  4. //创建一个窗口
  5. TicketWindow tw1=new TicketWindow();
  6.  
  7. //使用三个线程同时启动
  8. Thread t1=new Thread(tw1);
  9. Thread t2=new Thread(tw1);
  10. Thread t3=new Thread(tw1);
  11.  
  12. t1.start();
  13. t2.start();
  14. t3.start();
  15. }
  16.  
  17. }
  18.  
  19. //售票窗口类
  20. class TicketWindow implements Runnable{
  21. private int nums=2000; //一共2000张票
  22.  
  23. @Override
  24. public void run() {
  25. while(true){
  26.  
  27. if(nums>0){ //先判断是否还有票
  28. //Thread.currentThread().getName()得到当前线程的名字
  29. System.out.println(Thread.currentThread().getName()+"在售出第"+nums+"张票"); //显示售票信息
  30.  
  31. //出票的速度是一秒出一张
  32. try {
  33. Thread.sleep(1000);
  34. } catch (InterruptedException e) {
  35. e.printStackTrace();
  36. }
  37.  
  38. nums--;
  39. }else{
  40. break; //售票结束
  41. }
  42.  
  43. }
  44. }
  45. }

执行这段代码发现问题,就是同一张票号可能被多个售票窗口出售,惹祸的代码就是if else语句块。

解决方法就是在需要同步的代码段用synchronized(Object){你要同步的代码}即可。

修改后代码如下:

  1. public class Demo_5 {
  2.  
  3. public static void main(String[] args) {
  4. //创建一个窗口
  5. TicketWindow tw1=new TicketWindow();
  6.  
  7. //使用三个线程同时启动
  8. Thread t1=new Thread(tw1);
  9. Thread t2=new Thread(tw1);
  10. Thread t3=new Thread(tw1);
  11.  
  12. t1.start();
  13. t2.start();
  14. t3.start();
  15. }
  16.  
  17. }
  18.  
  19. //售票窗口类
  20. class TicketWindow implements Runnable{
  21. private int nums=2000; //一共2000张票
  22.  
  23. @Override
  24. public void run() {
  25. while(true){
  26. //认为if else这段代码要保证其原子性(同步代码块)
  27. synchronized (this) {
  28.  
  29. if(nums>0){ //先判断是否还有票
  30. //Thread.currentThread().getName()得到当前线程的名字
  31. System.out.println(Thread.currentThread().getName()+"在售出第"+nums+"张票"); //显示售票信息
  32.  
  33. //出票的速度是一秒出一张
  34. try {
  35. Thread.sleep(1000);
  36. } catch (InterruptedException e) {
  37. e.printStackTrace();
  38. }
  39.  
  40. nums--;
  41. }else{
  42. break; //售票结束
  43. }
  44.  
  45. }
  46. }
  47. }
  48. }

执行这段代码发现出票正常了。

线程1正执行需要做同步处理的代码,线程2,3,4……blocked,被放入了线程等待池,就好像某人上厕所前先把门关上(上锁),完事之后再出来(解锁),然后别人就可以继续使用了。

Java中如何解决线程安全问题的更多相关文章

  1. java 22 - 12 多线程之解决线程安全问题的实现方式1

    从上一章知道了多线程存在着线程安全问题,那么,如何解决线程安全问题呢? 导致出现问题的原因: A:是否是多线程环境 B:是否有共享数据 C:是否有多条语句操作共享数据 上一章的程序,上面那3条都具备, ...

  2. java线程安全问题以及使用synchronized解决线程安全问题的几种方式

    一.线程安全问题 1.产生原因 我们使用java多线程的时候,最让我们头疼的莫过于多线程引起的线程安全问题,那么线程安全问题到底是如何产生的呢?究其本质,是因为多条线程操作同一数据的过程中,破坏了数据 ...

  3. java并发之如何解决线程安全问题

    并发(concurrency)一个并不陌生的词,简单来说,就是cpu在同一时刻执行多个任务. 而Java并发则由多线程实现的. 在jvm的世界里,线程就像不相干的平行空间,串行在虚拟机中.(当然这是比 ...

  4. java 22 - 13 多线程之解决线程安全问题的实现方式2

    上一章说了,解决线程安全问题的实现方式1是使用同步代码块 同时也知道了,同步代码块的锁对象是任意对象:(Object obj ;  Demo d;)这些都行 那么,现在来说解决线程安全问题的实现方式2 ...

  5. Java之解决线程安全问题的方式三:Lock锁

    import java.util.concurrent.locks.ReentrantLock; /** * 解决线程安全问题的方式三:Lock锁 --- JDK5.0新增 * * 1. 面试题:sy ...

  6. ThreadLocal,Java中特殊的线程绑定机制

    在DRP项目中,我们使用了ThreadLocal来创建Connection连接,避免了一直以参数的形式将Connection向下传递(传递connection的目的是由于jdbc事务要求确保使用同一个 ...

  7. Lock锁方式解决线程安全问题

    在JDK5.0之后新增加了一种更强大的线程同步机制---通过显示定义同步锁来实现线程同步解决线程安全问题.同步锁使用Lock对象充当. java.util.concurrent.locks.lock接 ...

  8. Java-ThreadLocal,Java中特殊的线程绑定机制

    在DRP项目中,我们使用了ThreadLocal来创建Connection连接,避免了一直以参数的形式将Connection向下传递(传递connection的目的是由于jdbc事务要求确保使用同一个 ...

  9. 静态同步方法和解决线程安全问题_Lock锁

    静态的同步方法锁对象是谁?不能是thisthis是创建对象之后产生的,静态方法优先于对象静态方法的锁对象是本类的cLass属性-->class文件对象(反射) 卖票案例出现了线程安全问题 卖出了 ...

随机推荐

  1. 抓取git的log文件批处理命令示例

    @echoset sincedate="2016-04-28 00:00:01"          ::变量set beforedate="2016-04-29 00:0 ...

  2. python 3.x 学习笔记17(协程以及I/O模式)

    1.协程(微线程)协程是一种用户态的轻量级线程.协程拥有自己的寄存器上下文和栈.协程调度切换时,将寄存器上下文和栈保存到其他地方,在切回来的时候,恢复先前保存的寄存器上下文和栈.因此: 协程能保留上一 ...

  3. POJ 1995 Raising Modulo Numbers 【快速幂取模】

    题目链接:http://poj.org/problem?id=1995 解题思路:用整数快速幂算法算出每一个 Ai^Bi,然后依次相加取模即可. #include<stdio.h> lon ...

  4. canvas 画图优化

    http://www.cnblogs.com/rhcad/archive/2012/11/17/2774794.html

  5. ZBrush软件Texture纹理调控板

    在zbrush4r8中对一个模型进行纹理制作在速度和易用性方面有诸多优势,通过Texture调控板创建.导入和输出纹理是及其方便且快捷的. Import (导入):导入Photoshop (.psd) ...

  6. Eclipse中使用GIT将文件还原至上一版本

    GIT将文件还原至上一版本: 选中文件——右击——Replace With——HEAD Revision:

  7. MySQL 关闭 binlog 日志

    [关闭binlog日志] 1.vim /etc/my.cnf 注释如下内容: #log-bin=mysql-bin #binlog_format=mixed #server-id = 1 #expir ...

  8. Mysql ERROR 1067: Invalid default value for 字段

    问题: //今天把一个数据库的sql文件导入到另一个数据库出现以下异常: Mysql ERROR 1067: Invalid default value for 字段 //原因是因为之前导出数据里面有 ...

  9. HDU 1756 Cupid's Arrow( 判断点在多边形的内外 )

    链接:传送门 思路:判断每支箭是否在多边形内,计算几何点定位中水题,不清楚下面的代码能不能适用于给定点的顺序不确定( 既不是顺时针又不是逆时针 ) /************************* ...

  10. 全面的framebuffer详解

    一.FrameBuffer的原理    FrameBuffer 是出现在 2.2.xx 内核当中的一种驱动程序接口.    Linux是工作在保护模式下,所以用户态进程是无法象DOS那样使用显卡BIO ...