A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

  1. class SellTicket
  2. {
  3. public static void main(String[] args)
  4. {
  5. Ticket t1 = new Ticket();
  6. Ticket t2 = new Ticket();
  7. Ticket t3 = new Ticket();
  8. Ticket t4 = new Ticket();
  9. t1.start();
  10. t2.start();
  11. t3.start();
  12. t4.start();
  13. }
  14. }
  15. class Ticket extends Thread
  16. {
  17. Object obj = new Object();
  18. private static int tick = 100;
  19. public void run() // Thread-0..sale 0 Thread-1..sale -1 Thread-2..sale -2
  20. {
  21. while(true)
  22. {
  23. synchronized(obj) // Thread-0..sale 0 Thread-1..sale -1 Thread-2..sale -2
  24. {
  25. if (tick>0)
  26. {
  27. try{Thread.sleep(500);}catch(Exception e){}
  28. System.out.println(currentThread().getName()+"..sale "+tick--);
  29. }
  30. }

  31. }
  32. }
  33. }
  34. /*
  35. Thread-0..sale 0
  36. Thread-1..sale -1
  37. Thread-2..sale -2
  38. */
复制代码
关于Runnable接口进行的多线程产生的安全问题,及解决方案,这里不赘述。视频上面已经讲的很完整。但是对于extends Thread 的多线程安全问题,视频上面没有涉及,实际开发中,可能也不会用到。但是,作为一个小知识,可以了解一下。
这段代码运行到最后,必然出现Thread-0..sale 0  Thread-1..sale -1  Thread-2..sale -2。无论是使用public synchronized void run() {.....}   ,还是在public void run() {..synchronized(obj)...}中使用。都不能解决这种安全问题。

       解决方法就是,还是使用同步代码块,但是,在Object对象前面加上static 。-----说明,对于静态成员变量作为共享数据时,对象锁也必须是静态的。



5 个回复

正序浏览
有陷阱快跑丶 发表于 2014-12-21 19:05
因为你访问的资源不是公共的。不定义在成员位置就行,你把票单独封装成一个类。这样就行了 ...

求教:一个代码,使用同步函数,如何保证安全问题呢?
  1. class SellTicket
  2. {
  3.         public static void main(String[] args)
  4.         {
  5.                 Ticket t1  = new Ticket();
  6.                 Ticket t2  = new Ticket();
  7.                 Ticket t3  = new Ticket();
  8.                 Ticket t4  = new Ticket();
  9.                 t1.start();
  10.                 t2.start();
  11.                 t3.start();
  12.                 t4.start();
  13.         }
  14. }
  15. class Ticket extends Thread
  16. {
  17.         //static Object obj = new Object();
  18.         private static int tick = 1000;
  19.         public void run() // Thread-0..sale  0  Thread-1..sale  -1 Thread-2..sale  -2
  20.         {
  21.                 while(true)
  22.                 {
  23.                         //synchronized(obj)  // Thread-0..sale  0  Thread-1..sale  -1 Thread-2..sale  -2
  24.                         //{
  25.                                 show();
  26.                         //}
  27.                
  28.                 }
  29.         }
  30.         public synchronized void show()
  31.         {
  32.                 if (tick>0)
  33.                 {
  34.                         try{Thread.sleep(10);}catch(Exception e){}
  35.                         System.out.println(currentThread().getName()+"..Thread-sale  "+tick--);
  36.                 }
  37.         }
  38. }
复制代码
回复 使用道具 举报
因为你访问的资源不是公共的。不定义在成员位置就行,你把票单独封装成一个类。这样就行了
回复 使用道具 举报
程梦真 发表于 2014-12-21 18:49
原来是分享帖,我还以为是求教帖,献丑- -。

我过我还是觉得是在线程中直接是用synchronize是很不规范的
回复 使用道具 举报
原来是分享帖,我还以为是求教帖,献丑- -。
回复 使用道具 举报
我扫了一下你的程序,发现几个问题,为何你在线程内使用synchronized,用随便new的一个object来监视有什么意思。。。希望你静下心来 多看看视频 多看看书。 我以前也跟你一样,切记学习不可心浮气躁
介绍2个经验给你 至少我这周看了一半的《java多线程设计模式》都是这样做的,synchronized一般在线程调用的实例的方法中使用,至少我还没见过这里面有在线程中使用的(这一点有待我继续学习),监视对象一般是用线程调用的实例本身,或者类.class(类.class表示监视这一类型的jvm中的所有实例)
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马