黑马程序员技术交流社区

标题: 同步问题代码排错 [打印本页]

作者: 祁振朋    时间: 2013-3-19 00:04
标题: 同步问题代码排错
本帖最后由 祁振朋 于 2013-3-19 18:04 编辑
  1. class FourTicket
  2. {
  3. public static void main(String[] args)
  4. {
  5. new TicketSeller ().start();
  6. new TicketSeller ().start();
  7. new TicketSeller ().start();
  8. new TicketSeller ().start();

  9. }
  10. }

  11. class TicketSeller extends Thread
  12. {
  13. private static int ticket=100;
  14. private Object obj=new Object();
  15. public void run(){

  16. while (true)
  17. {
  18. synchronized(obj)
  19. {
  20. if(ticket<=0)
  21. {break;}

  22. try
  23. {
  24. Thread.sleep(1000);
  25. }
  26. catch (Exception e)
  27. {
  28. e.printStackTrace();
  29. }

  30. System.out.println(getName()+"售出第"+ticket +"张票");
  31. ticket--;
  32. }
  33. }
  34. }
  35. }
复制代码
编译没错,可是不能实现同步。请问是哪儿错了?
作者: 李尧    时间: 2013-3-19 00:17
我复制你的代码测试了一下,问题可能是出在第16行:private Object obj=new Object();
你每次new TicketSeller ().start(); 也就new了一个Object(); 这样你4个线程用的4个Object对象,锁不唯一,所以就不同步了.
改成 private static Object obj=new Object(); 再试试看.
这是我个人看法,坐等高人给出更专业的解释.
作者: 曹玉龙    时间: 2013-3-19 00:40
本帖最后由 曹玉龙 于 2013-3-19 00:45 编辑

锁不结实,换把锁就好了,代码如下:
  1. class FourTicket {
  2.         public static void main(String[] args) {
  3.                 new TicketSeller().start();
  4.                 new TicketSeller().start();
  5.                 new TicketSeller().start();
  6.                 new TicketSeller().start();

  7.         }
  8. }

  9. class TicketSeller extends Thread {
  10.         private static int ticket = 100;
  11.        

  12.         public void run() {

  13.                 while (true) {
  14.                         //用本类作锁即可
  15.                         synchronized (TicketSeller.class) {
  16.                                 if (ticket <= 0) {
  17.                                         break;}
  18.                                         try {
  19.                                                 Thread.sleep(1000);
  20.                                         } catch (Exception e) {
  21.                                                 e.printStackTrace();
  22.                                         }

  23.                                         System.out.println(getName() + "售出第" + ticket + "张票");
  24.                                         ticket--;                               
  25.                         }
  26.                 }
  27.         }
  28. }
复制代码

作者: 杨玉辉    时间: 2013-3-19 00:44
本帖最后由 杨玉辉 于 2013-3-19 00:50 编辑

兄弟这个不多解释,实现同时卖票,线程同步就需要卖的是同一个资源:ticket

这时你的视频内容未看到后面的更深的知识点,建议你能弄懂这个练习锁,要表达的意思就是锁的作用,要想实现同步,还需共享资源(后面的视频可以看到)

至于下图出现负数的情况,完全是因为缺少必要的线程锁,出现了线程的等待唤醒机制的时候,不同线程抢夺了cpu 执行权,这些内容后面的视频都有涉及。

到时候你要做的就是,回头再来复习一下,加深理解synchronized 的作用,看看是不是有新的收获

ADJP8)7K80`E5LFJ1TGTK@I.jpg (43.72 KB, 下载次数: 1)

ADJP8)7K80`E5LFJ1TGTK@I.jpg

作者: 杨玉辉    时间: 2013-3-19 00:44
本帖最后由 杨玉辉 于 2013-3-19 00:46 编辑

奇怪,还会有重复内容,改了

作者: 谭辉    时间: 2013-3-19 10:33
本帖最后由 谭辉 于 2013-3-19 10:38 编辑

问题在于你创建线程时,new了四个不同的对象启动线程,自然四个线程的锁不是同一个锁;
可以把锁改成TicketSeller.class,或者用实现Runable接口的方式创建线程
  1. class FourTicket
  2. {
  3. public static void main(String[] args)
  4. {
  5.         TicketSeller t=new TicketSeller();
  6.         Thread t1=new Thread(t);
  7.         Thread t2=new Thread(t);
  8.         Thread t3=new Thread(t);
  9.         Thread t4=new Thread(t);
  10.         t1.start();
  11.         t2.start();
  12.         t3.start();
  13.         t4.start();
  14. }
  15. }

  16. class TicketSeller implements Runnable
  17. {
  18. private static int ticket=100;
  19. private Object obj=new Object();
  20. public void run(){

  21. while (true)
  22. {
  23. synchronized(obj)
  24. {
  25. if(ticket<=0)
  26. {break;}

  27. try
  28. {
  29. Thread.sleep(10);
  30. }
  31. catch (Exception e)
  32. {
  33. e.printStackTrace();
  34. }

  35. System.out.println(Thread.currentThread().getName()+"售出第"+ticket +"张票");
  36. ticket--;
  37. }
  38. }
  39. }
  40. }
复制代码

作者: 陈丽莉    时间: 2013-3-19 14:40
若还有问题,请继续追问;没有的话,请将帖子分类改成【已解决】~




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2