我看了下别的大神的博客。结合自己的练习了下多线程的并发问题。我觉得就多线程而言。最重要的就是要把整个业务放进同步锁里面。
synchronized这个关键字有两种用法1、放方法名前形成同步方法;2、放在块前构成同步块。
比如:
class thread4Test implements Runnable{ private int ticket=10; public synchronized void run() { for(int i=1;i<50;i++) { if(ticket>0) { //休眠1s秒中,为了使效果更明显,否则可能出不了效果 try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"号窗口卖出"+this.ticket--+"号票"); } } } }
输出结果是
a号窗口卖出10号票
a号窗口卖出9号票
a号窗口卖出8号票
a号窗口卖出7号票
a号窗口卖出6号票
a号窗口卖出5号票
a号窗口卖出4号票
a号窗口卖出3号票
a号窗口卖出2号票
a号窗口卖出1号票
这里的同步锁的位置是在run方法里面。同步的是run方法。这样的话启动一条线程之后就会一直运行。直到a执行完毕之后b再去执行的时候就没有票了。
例如:
class thread5Test implements Runnable{ private int ticket=10; public void run() { for(int i=1;i<50;i++) { if(ticket>0) { synchronized(this){ //休眠1s秒中,为了使效果更明显,否则可能出不了效果 try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"号窗口卖出"+this.ticket--+"号票"); } } } } }
执行结果:
a号窗口卖出10号票
c号窗口卖出9号票
b号窗口卖出8号票
b号窗口卖出7号票
b号窗口卖出6号票
b号窗口卖出5号票
c号窗口卖出4号票
a号窗口卖出3号票
a号窗口卖出2号票
a号窗口卖出1号票
c号窗口卖出0号票
b号窗口卖出-1号票
synchronized放错了位置,程序将synchronized放在了if语句的后面,当b线程取出2好票以后,此时ticket=1,等下一次a、b、c线程来的时候,ticket=1>0就进入if语句体,这时cpu分给线程的时间片是先b在c后a这样就导致了上面的结果。
例如:
class thread6Test implements Runnable{ private int ticket=10; public void run() { synchronized(this){ for(int i=1;i<50;i++) { if(ticket>0) { //休眠1s秒中,为了使效果更明显,否则可能出不了效果 try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"号窗口卖出"+this.ticket--+"号票"); } } } }
输出结果:
这里的执行结果也是只有a售票。因为同步锁的时候同步了整个的循环。
整个程序的业务是什么?业务就是售票。换句话说。就是说要售票的时候不能出错。售票的时候各个窗口还有业务彼此不能相互交叉干扰。
当一个线程要使用火车票这个资源时,我们就交给它一把锁,等它把事情做完后在把锁给另一个要用这个资源的线程
那么。同步的时候就不是同步程序了。应该是同步销售火车票的这个业务。例如:
class thread3Test implements Runnable{ private int ticket=10; public void run(){ for(int i=1;i<50;i++){ if(ticket>0){ try { Thread.sleep(1000); } catch (Exception e) { e.printStackTrace(); } this.sale(); } } } public synchronized void sale(){ if(ticket>0){System.out.println(Thread.currentThread().getName()+"号窗口卖出第"+this.ticket--+"张票!");} } }
这里销售火车票就是业务。在这里同步的时候同步业务,而不是同步后台的票的处理的程序。票就算是再处理出来的也是票。
处理的时候是处理的业务。也就是售票。那么,只要售票的时候不会出现问题就好。同步应该放在业务上,而不是票的处理上。
我是小菜鸟。这也是我第一次写博客。希望大家能够不吝啬的多多的指教。同时,也感谢各位大师。大神们在博客园的分享。让我学到了很多东西。
在此,我也把我的一点小小的经验分享出来。希望更多的人能够参与到其中来。
我也说了。我也是一直小菜鸟。希望大家能够给我多多的指教。我只是写出来了一点我自己的看法还有经验。
编程这个东西是一个务实,严谨的工作。只有经得起考验的程序才是好的程序。
在此。也希望大家能够给我多多的指教。提供更多的看法。我也会虚心的采纳。不断的学习。不断的成长。