BBYR Achieve
返回信息流
这是一条镜像帖。来源:北邮人论坛 / java / #60540同步于 2018/11/30
该镜像源已超过 30 天没有更新,可能在源站已被删除。
Java机器人发帖

这个程序有问题吧?读书看到的

zidian321
2018/11/30镜像同步8 回复
Java 高并发编程详解 第64页 关于Synchronized的使用 示例程序,这个程序逻辑有问题吧,每次运行只有一个线程能打印所有数据,其他两个线程得到锁的时候,都打印完了····根本不是并行打印。 public class TicketWindowRunnable implements Runnable{ private int index = 1 ; private final static int MAX = 500; private final static Object Mutex = new Object(); public void run() { synchronized(Mutex) { while(index<=MAX) { System.out.println(Thread.currentThread()+" 的号码是" + index++); } }} public static void main(String[] args) { final TicketWindowRunnable task = new TicketWindowRunnable(); Thread windowThread1 = new Thread(task,"一号窗口"); Thread windowThread2 = new Thread(task,"二号窗口"); Thread windowThread3 = new Thread(task,"三号窗口"); windowThread1.start(); windowThread2.start(); windowThread3.start(); } }
订阅后,新回复会通过你的通知中心匿名送达。
8 条回复
lycxy机器人#1 · 2018/11/30
因为处理的太快了吧,sleep1秒看看
Nroskill机器人#2 · 2018/11/30
本来就不能算是并行的……关键逻辑都加锁了 另外楼上是对的,MAX=500太小了,你自己加一秒然后break看看,起码能加到上亿的
qq825503975机器人#3 · 2018/11/30
许多书籍都有错,看明白就OK。不确定的话,实践一下,尤其在初学阶段 【 在 zidian321 (tomato) 的大作中提到: 】 : Java 高并发编程详解 第64页 关于Synchronized的使用 示例程序,这个程序逻辑有问题吧,每次运行只有一个线程能打印所有数据,其他两个线程得到锁的时候,都打印完了····根本不是并行打印。 : public class TicketWindowRunnable implements Runnable{ : private int index = 1 ; : ...................
damnid机器人#4 · 2018/12/1
一选火枪
MrDXY机器人#5 · 2018/12/1
我的理解:确实是会有一个线程一直获得锁,直到数组遍历打印结束(都在一个线程中执行完成),其实并不是程序执行过快导致的,就是因为其他线程同步代码块没有获得锁,所以不能打印。原文里也只是说,加上关键字避免了多线程处理数据不一致的问题,所以也没说错。 1. 如果你想要让多个线程都能打印,就要线程每打印一次,跳出同步代码块,让其他线程也能获得锁。 2. 如果你想让结果更明确一些,比如不要让一个线程连续打印,就可以加个sleep,让当前线程继续执行同步块之外的代码,好让剩余的其他两个线程去竞争锁。 package TicketWindowRunnable; public class TicketWindowRunnable implements Runnable{ private int index = 1 ; private final static int MAX = 500; private final static Object Mutex = new Object(); public void run() { while(true) { try { out: synchronized (Mutex) { while (index <= MAX) { System.out.println(Thread.currentThread() + " 的号码是" + index++); break out; } } Thread.sleep(100); }catch (InterruptedException e){ e.printStackTrace(); } } } public static void main(String[] args) { final TicketWindowRunnable task = new TicketWindowRunnable(); Thread windowThread1 = new Thread(task,"一号窗口"); Thread windowThread2 = new Thread(task,"二号窗口"); Thread windowThread3 = new Thread(task,"三号窗口"); windowThread1.start(); windowThread2.start(); windowThread3.start(); } } 因为是一个叫号的程序,所以叫号之后你加上个“处理业务的时间”,就能实现“同一个窗口”,不会“连续叫号”的情况。 附上结果:
xuanyu66机器人#6 · 2018/12/1
因为syncronized是非公平锁,当你一个任务运行特别快的时候是可能发生这种情况的。 而且就是如果你运行一次的时间小于切换上下文的时间,那这个场景就不适合并发。 可以去了解一下锁底层的优化,偏向锁,轻量级锁
bearsmall机器人#7 · 2018/12/1
没看过这本书,看代码,synchronized代码块包裹了while,然后代码的整个逻辑就是while代码块,所以这么写其实就一个任务,然后分配到了一个线程,然后跑完while就执行完了,释放锁,没毛病。其它线程因为没有获得锁所以都饿死了,等第一个线程跑完释放锁,后面的线程获取锁后跑到while这里一看发现“活都干完了啊,好像没我什么事,一脸懵逼”。多线程卖票的话同步代码块应该放到while循环里面才对,这样线程们才又机会去竞争。我是这么理解的。另外synchronized释放锁一般在1.当前线程同步代码块执行结束(你贴的代码这里就是整个while部分);2.当前线程遇到break 、 return ;3.当前线程出现未处理的error或者exception导致异常结束;4.当前线程程序执行了同步对象wait方法 ,当前线程暂停,释放锁;另外像当前线程程序调用 Thread.sleep()、Thread.yield() 这些方法能暂停线程的执行,但是并不会释放锁,所以你贴的这代码想靠sleep“看效果”是没用的。
bearsmall机器人#8 · 2018/12/1
当然,从细节看,把synchronize提到while里面后还有一个细节,你要保证不“多卖票”的话还需要在输出那判断一下if(index<=MAX),不然很可能就多卖两张票了。。。。。 【 在 bearsmall 的大作中提到: 】 : 没看过这本书,看代码,synchronized代码块包裹了while,然后代码的整个逻辑就是while代码块,所以这么写其实就一个任务,然后分配到了一个线程,然后跑完while就执行完了,释放锁,没毛病。其它线程因为没有获得锁所以都饿死了,等第一个线程跑完释放锁,后面的线程获取锁后跑到while这里一看发现“活都干完了啊,好像没我什么事,一脸懵逼”。多线程卖票的话同步代码块应该放到while循环里面才对,这样线程们才又机会去竞争。我是这么理解的。另外synchronized释放锁一般在1.当前线程同步代码块执行结束(你贴的代码这里就是整个while部分);2.当前线程遇到break 、 return ;3.当前线程出现未处理的error或者exception导致异常结束;4.当前线程程序执行了同步对象wait方法 ,当前线程暂停,释放锁;另外像当前线程程序调用 Thread.sleep()、Thread.yield() 这些方法能暂停线程的执行,但是并不会释放锁,所以你贴的这代码想靠sleep“看效果”是没用的。