精华帖 (3) :: 良好帖 (0) :: 新手帖 (2) :: 隐藏帖 (6)
|
|
---|---|
作者 | 正文 |
发表时间:2011-07-05
楼主的逻辑思维能力确实不错,尤其是在实践经验不多的情况下,就能分析出可能出现的死锁。
会用blockingqueue和会写blocingqueue是不一样的,鼓励楼主继续研究。 |
|
返回顶楼 | |
发表时间:2011-07-05
最后修改:2011-07-05
taolei0628 写道 楼主的逻辑思维能力确实不错,尤其是在实践经验不多的情况下,就能分析出可能出现的死锁。
会用blockingqueue和会写blocingqueue是不一样的,鼓励楼主继续研究。 谢鼓励 哈哈 |
|
返回顶楼 | |
发表时间:2011-07-05
AngelAndAngel 写道 taolei0628 写道 楼主的逻辑思维能力确实不错,尤其是在实践经验不多的情况下,就能分析出可能出现的死锁。
会用blockingqueue和会写blocingqueue是不一样的,鼓励楼主继续研究。 这东西实践经验确实不多 主要是用的机会不太多 没有遇到过太复杂的东西 我也相当于学习了 光用的话LinkedBlockingQueue确实不难。 |
|
返回顶楼 | |
发表时间:2011-07-05
AngelAndAngel 写道 samttsch 写道 public class BlockingQ
{ private Object notEmpty = new Object(); private Object notFull = new Object(); private Queue<Object> linkedList = new LinkedList<Object>(); private int maxlength = 10; public Object take() throws InterruptedException{ synchronized (notEmpty){ if(linkedList.size()==0) { notEmpty.wait(); } synchronized (notFull){ if(linkedList.size() == maxlength){ notFull.notifyAll(); } return linkedList.poll(); } } } public Object offer(Object object) throws InterruptedException{ synchronized (notEmpty){ if(linkedList.size()==0) { notEmpty.notifyAll(); } synchronized (notFull){ if(linkedList.size() == maxlength){ notFull.wait(); } return linkedList.add(object); } } } } 这段代码是死锁的示例代码。哈哈。当A线程到达take的时候,发觉linkedList.size()==0,然后开始wait,等待释放notEmpty上的锁,这个时候B线程到达offer,开始add,add了几次后,发觉已到上线,然后wait,等待释放notFull上的锁,但是要释放notFull上的锁,必须要先进入take的notEmpty锁,而notEmpty锁,也在等待offer中的notEmpty锁释放,ok,死了。所以你这段代码是不行滴。 请你亲自测试过在发表意见,不要随便看看就下结论,尤其是连代码都还没看清楚 take: synchronized (notEmpty){ if(linkedList.size()==0) { ///A 进入到这里发现没有,则等待 notEmpty.wait(); } synchronized (notFull){ if(linkedList.size() == maxlength){ notFull.notifyAll(); } return linkedList.poll(); } } offer: synchronized (notEmpty){ if(linkedList.size()==0) { //B 进入到这里 发现没有数据,唤醒A,A等待CPU notEmpty.notifyAll(); } synchronized (notFull){ if(linkedList.size() == maxlength){ notFull.wait(); } return linkedList.add(object); } } |
|
返回顶楼 | |
发表时间:2011-07-05
samttsch 写道 AngelAndAngel 写道 samttsch 写道 public class BlockingQ
{ private Object notEmpty = new Object(); private Object notFull = new Object(); private Queue<Object> linkedList = new LinkedList<Object>(); private int maxlength = 10; public Object take() throws InterruptedException{ synchronized (notEmpty){ if(linkedList.size()==0) { notEmpty.wait(); } synchronized (notFull){ if(linkedList.size() == maxlength){ notFull.notifyAll(); } return linkedList.poll(); } } } public Object offer(Object object) throws InterruptedException{ synchronized (notEmpty){ if(linkedList.size()==0) { notEmpty.notifyAll(); } synchronized (notFull){ if(linkedList.size() == maxlength){ notFull.wait(); } return linkedList.add(object); } } } } 这段代码是死锁的示例代码。哈哈。当A线程到达take的时候,发觉linkedList.size()==0,然后开始wait,等待释放notEmpty上的锁,这个时候B线程到达offer,开始add,add了几次后,发觉已到上线,然后wait,等待释放notFull上的锁,但是要释放notFull上的锁,必须要先进入take的notEmpty锁,而notEmpty锁,也在等待offer中的notEmpty锁释放,ok,死了。所以你这段代码是不行滴。 请你亲自测试过在发表意见,不要随便看看就下结论,尤其是连代码都还没看清楚 take: synchronized (notEmpty){ if(linkedList.size()==0) { ///A 进入到这里发现没有,则等待 notEmpty.wait(); } synchronized (notFull){ if(linkedList.size() == maxlength){ notFull.notifyAll(); } return linkedList.poll(); } } offer: synchronized (notEmpty){ if(linkedList.size()==0) { //B 进入到这里 发现没有数据,唤醒A,A等待CPU notEmpty.notifyAll(); } synchronized (notFull){ if(linkedList.size() == maxlength){ notFull.wait(); } return linkedList.add(object); } } 这段代码我刚试验过了 发生死锁了 不信你试试 。还有根据你的注释,B进入后虽然唤醒A,但是由于下面将要出现的wait,仍然没有释放,所以B仍然不会得到。 |
|
返回顶楼 | |
发表时间:2011-07-05
将你的测试代码贴上来
|
|
返回顶楼 | |
发表时间:2011-07-05
samttsch 写道 将你的测试代码贴上来
我的代码如下: public class BlockOperator1 extends BlockOperator { private Object notEmpty = new Object(); private Object notFull = new Object(); private int maxlength = 3; private Queue<Object> linkedList = new LinkedList<Object>(); /** * 取物品 * * @return * @throws InterruptedException */ public Object take() throws InterruptedException { synchronized (notEmpty) { String cureadname = Thread.currentThread().getName(); System.out.println("搬运工" + cureadname + "来到仓库"); sleep(1000l); if (linkedList.size() == 0) { // 假如仓库没东西了,那么就先不取物品,此时释放锁,被唤醒之前,需要先得到锁 System.out.println("搬运工" + cureadname + "发觉没有物品,只能等待生产"); notEmpty.wait(); } synchronized (notFull) { if (linkedList.size() == maxlength) { notFull.notifyAll(); } Object obj = linkedList.poll(); System.out.println("搬运工" + cureadname + "这时看到有了物品,搬出了:" + obj + "仓库还有物品数量:" + linkedList.size()); return obj; } } } // 生产物品 public void offer(Object object) throws InterruptedException { synchronized (notEmpty) { String cureadname = Thread.currentThread().getName(); System.out.println("生产工" + cureadname + "来到仓库准备放物品"); sleep(3000l); if (linkedList.size() == 0) { // 假如仓库没东西了,唤醒对象锁。分析:这个时候有可能没有等待锁,也可能有。 System.out.println("生产工" + cureadname + "发现来到仓库的时候一件物品都没有,发觉搬运工在睡觉等他或者感觉搬运工在等他,于是喊醒了它"); notEmpty.notifyAll(); /* * 注 假如仓库有东西,那么不用唤醒搬运工,因为有物品的时候,搬运工不会等待。 * 分析:有的人肯定会觉得,有没有这种可能:当linkedList.size=0的时候,notEmpty就wait了,然后在本同步块中, * 发现linkedList.size!=0,那么notEmpty就不会去唤醒了。其实这完全没有可能,因为size!=0只有在完成了 * linkedList.add之后才有可能,而在add之前,必然会判断size=0的情况 */ } synchronized (notFull) { if (linkedList.size() == maxlength) { System.out.println("生产工" + cureadname + "发觉已到上线 notFull等待" ); notFull.wait(); } System.out.println("生产工" + cureadname + "把物品" + object + "放到了仓库"); linkedList.add(object); } } } private void sleep(Long time) { try { Thread.sleep(time);// 模拟时间消耗 } catch (InterruptedException e) { e.printStackTrace(); } } } |
|
返回顶楼 | |
发表时间:2011-07-05
你说的是对的,确实有问题!!!
public class BlockingQ { private Object notEmpty = new Object(); private Object notFull = new Object(); private Queue linkedQueue = new LinkedList(); private int maxlength = 3; public Object get() throws InterruptedException{ System.out.println("准备取出"); synchronized (notEmpty) { System.out.println("获得notEmpty锁"); if(linkedQueue.size() == 0){ System.out.println("队列为空。。等待"); notEmpty.wait(); } synchronized (notFull) { System.out.println("是否还保留notEmpty锁 "+Thread.holdsLock(notEmpty)); System.out.println("获得notFull锁"); if(linkedQueue.size() == maxlength){ System.out.println("队列满 通知放入的线程"); notFull.notifyAll(); } System.out.println("取出一个"); return linkedQueue.poll(); } } } public void offer(Object obj) throws InterruptedException{ System.out.println(" 准备放入"); synchronized (notEmpty) { System.out.println(" 获得notEmpty锁"); if(linkedQueue.size() == 0){ System.out.println(" 队列为空。。通知"); notEmpty.notifyAll(); } synchronized (notFull) { System.out.println(" 是否还保留notEmpty锁 "+Thread.holdsLock(notEmpty)); System.out.println(" 获得notFull锁"); if(linkedQueue.size() == maxlength){ System.out.println(" 等待取出的线程"); notFull.wait(); } System.out.println(" 放入一个"); linkedQueue.add(obj); } } } static class GetWorker implements Runnable { BlockingQ queue = null; GetWorker(BlockingQ q){ this.queue = q; } public void run(){ while(true){ try { queue.get(); Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } } } } static class PutWorker implements Runnable { BlockingQ queue = null; PutWorker(BlockingQ q){ this.queue = q; } public void run(){ while(true){ try { queue.offer(new Object()); Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } } public static void main(String[] args) { BlockingQ q = new BlockingQ(); new Thread(new GetWorker(q)).start(); new Thread(new PutWorker(q)).start(); } } 经过测试发现,线程在“内部锁”处等待时,“外部锁”是不会释放的,所以当队列满了之后会出现死锁的情况。 |
|
返回顶楼 | |
发表时间:2011-07-05
建议还是用并发包中的类吧,自己写还是不保险
|
|
返回顶楼 | |
发表时间:2011-07-05
samttsch 写道 建议还是用并发包中的类吧,自己写还是不保险
恩 那是。 |
|
返回顶楼 | |