黑马程序员技术交流社区

标题: 多线程售票和生产消费者例子对比的问题 [打印本页]

作者: 8047107    时间: 2013-6-25 19:07
标题: 多线程售票和生产消费者例子对比的问题
本帖最后由 孙百鑫 于 2013-6-30 08:46 编辑

在 Java基础视频教程第11天-09-多线程(多线程的安全问题)  里面售票可能出现负票会出现安全问题.
是因为多线程操作时候可能中间的一个线程处于临时状态,这时候其他进程进来了.后来这个线程正常后也还是操作共享数据导致的.
所以加了同步锁,线程0进来  线程1就进不来了...可以解决这个问题.
这个是没有问题的.....



在  Java基础视频教程第12天-05-多线程(线程间通信-生产者消费者) 这个例子里面

有个resources的类.里面有同步函数,这时候创建两个生产者线程,2个消费者线程,但是同步了为什么生产者0的线程进入了 生产者1的线程还可以进入?已经在函数加锁了啊. 不是线程0有锁进入之后,线程1不就没锁进入不了了么!?
他们的锁都是同一个啊...而且操作的是共享数据啊.(生产出来的商品的编号..)

作者: 万琪    时间: 2013-6-25 20:22
大牛,看看是不是因为多核CPU的问题
作者: 8047107    时间: 2013-6-25 20:37
万琪 发表于 2013-6-25 20:22
大牛,看看是不是因为多核CPU的问题

前两个字打错了吧??
不是多核..就一般机器..
我是今天看了视频消费者的那个视频 才觉得迷惑
作者: 8047107    时间: 2013-6-25 23:42
顶起来一下
作者: 袁梦希    时间: 2013-6-26 01:44
很好
作者: majunm    时间: 2013-6-26 09:42
把 if(flag)改成while(flag) 循环
作者: tpsu88    时间: 2013-6-26 09:56
但是同步了为什么生产者0的线程进入了 生产者1的线程还可以进入?已经在函数加锁了啊.

答:首先t1抢到执行权,此时flag初始值是false,不执行wait,所以生产了一个,再往下他把flag改成了true,然后notify唤醒了其他线程(这就是关键!),t1回头判断if(flag)是true,所以就wait了。
此时t2抢到执行权,判断if,也是真,所以也挂那了!!
所以关键是t1唤醒了其他线程,t2才进来的。并不是t1上来就挂那了!
作者: 郭伟杰    时间: 2013-6-26 11:06
你到底想说什吗              
作者: 郭伟杰    时间: 2013-6-26 14:47
你怎么得的技术分啊   那么高   分享一下
作者: 8047107    时间: 2013-6-27 21:08
袁梦希 发表于 2013-6-26 01:44
很好

我听视频里的意思好像就是一个线程wait之后 其他线程就可以继续了....就像没锁一样 ~
改为解决了把
作者: 8047107    时间: 2013-6-27 21:09
tpsu88 发表于 2013-6-26 09:56
但是同步了为什么生产者0的线程进入了 生产者1的线程还可以进入?已经在函数加锁了啊.

答:首先t1抢到执行 ...

我的意思就是 t1睡了之后 t2是否就可以直接进来?就这个简单的意思.....你误解了
作者: 罗广伟    时间: 2013-6-27 22:03
主要是wait()的问题,线程读到wait()后就会等待唤醒,并且释放锁。等被唤醒之后再继续强cpu执行权,抢到后接着执行上次wait()后的代码,不会从加锁位置开始读代码的。
作者: 孙百鑫    时间: 2013-6-30 08:45
楼主您好,帖子长时间没有动态我已经将您的帖子改成已解决。如有问题请私密我哦~
作者: 宋旭东    时间: 2013-7-2 21:15
两点:
|--if:只判断一次
|--notify():随机唤醒任意一个线程

解释:
生产者0进入后,随机唤醒一个线程,生产者1可能被唤醒,进入,由于if只判断一次,生产者1来时条件还满足条件,也进入了,就造成了你说的现象。
解决:
将if判断换成while 循环判断,把notify()方法,换成notifyAll()方法,如果是环形的生产者1,条件不满足就进不来,如果是消费者的就可以。问题会被解决。
优化解决:
使用Lock类来解决。





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