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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© Tauruszzy 中级黑马   /  2015-5-13 15:10  /  237 人查看  /  0 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

为了解决多线程的安全问题,为什么这么说呢?
请看代码一的执行结果:
代码一
  1. class Ticket implements Runnable
  2. {
  3.         private int tick=100;
  4.         public void run()
  5.         {
  6.                 while(true)
  7.                 {
  8.                         if(tick>0)
  9.                         {
  10.                                 try
  11.                                 {
  12.                                         Thread.sleep(10);
  13.                                 }
  14.                                 catch (Exception e)
  15.                                 {
  16.                                 }
  17.                                 System.out.println(Thread.currentThread().getName()+"...sale:"+tick--);
  18.                         }
  19.                 }
  20.         }
  21. }
  22. class  TicketDemo
  23. {
  24.         public static void main(String[] args)
  25.         {
  26.                 Ticket t=new Ticket();
  27.                 Thread t1=new Thread(t);
  28.                 Thread t2=new Thread(t);
  29.                 Thread t3=new Thread(t);
  30.                 Thread t4=new Thread(t);
  31.                 t1.start();
  32.                 t2.start();
  33.                 t3.start();
  34.                 t4.start();
  35.         }
  36. }
复制代码

代码一执行结果:
  1. Thread-0...sale:10
  2. Thread-2...sale:9
  3. Thread-3...sale:8
  4. Thread-1...sale:7
  5. Thread-0...sale:6
  6. Thread-2...sale:5
  7. Thread-3...sale:4
  8. Thread-1...sale:3
  9. Thread-0...sale:2
  10. Thread-2...sale:1
  11. Thread-3...sale:0
  12. Thread-0...sale:-1//1
  13. Thread-1...sale:-2//2
复制代码

上面的售票例子中出现了负值,与事实相悖,原因是多个线程共享的数据出现了问题,为了解决这个问题,我们需要在共享的语句范围内确保只有一个线程在运行,当一个线程运行结束本次执行权后,再允许下一个线程的运行,这里引入同步代码块的机制,看下面的代码:
代码2
  1. class Ticket implements Runnable
  2. {
  3.         private int tick=100;
  4.         Object obj=new Object();//定义需要传入的对象
  5.         public void run()
  6.         {
  7.                 while(true)
  8.                 {
  9.                         synchronized(obj)//同步代码块
  10.                         {
  11.                                 if(tick>0)
  12.                                 {
  13.                                 try
  14.                                 {
  15.                                         Thread.sleep(10);//睡眠10毫秒
  16.                                 }
  17.                                 catch (Exception e)
  18.                                 {
  19.                                 }
  20.                                 System.out.println(Thread.currentThread().getName()+"...sale:"+tick--);
  21.                                 }
  22.                         }
  23.                        
  24.                 }
  25.         }
  26. }
  27. class  TicketDemo
  28. {
  29.         public static void main(String[] args)
  30.         {
  31.                 Ticket t=new Ticket();
  32.                 Thread t1=new Thread(t);
  33.                 Thread t2=new Thread(t);
  34.                 Thread t3=new Thread(t);
  35.                 Thread t4=new Thread(t);
  36.                 t1.start();
  37.                 t2.start();
  38.                 t3.start();
  39.                 t4.start();
  40.         }
  41. }
复制代码

总结:
/*
对象如同锁。持有锁的线程可以在同步中执行。
没有持有锁的线程即使获取cpu的执行权,也进不去,因为没有获取锁。

同步的前提:
1,必须要有两个或者两个以上的线程。
2,必须是多个线程使用同一个锁。
必须保证同步中只能有一个线程在运行。
好处:解决了多个线程的安全问题。
弊端:多个线程需要判断锁,较为消耗资源。
           -------------黑马视频--毕老师
*/

0 个回复

您需要登录后才可以回帖 登录 | 加入黑马