职业IT人-IT人生活圈

 找回密码
 成为会员
搜索
查看: 481|回复: 11

关于多线程的一个面试题,欢迎大家来讨论

  [复制链接]
曾经的小孩 发表于 2011-9-7 10:12 | 显示全部楼层 |阅读模式
一个被锁的老帖
===========================================================================
下面的代码在绝大部分时间内都运行得很正常,请问在什么情况下会出现问题?问题的根源在哪里?
Java代码  
package com.heyongjin.test;   
  
import java.util.LinkedList;   
  
public class Stack {   
  
    LinkedList list = new LinkedList();   
  
    public synchronized void push(Object x) {   
        synchronized (list) {   
            list.addLast(x);   
            notify();   
        }   
    }   
  
    public synchronized Object pop() throws Exception {     
        synchronized (list) {   
            if (list.size() <= 0) {   
                wait();   
            }   
            return list.removeLast();   
        }   
    }   
}  

package com.heyongjin.test;

import java.util.LinkedList;

public class Stack {

        LinkedList list = new LinkedList();

        public synchronized void push(Object x) {
                synchronized (list) {
                        list.addLast(x);
                        notify();
                }
        }

        public synchronized Object pop() throws Exception {  
                synchronized (list) {
                        if (list.size() <= 0) {
                                wait();
                        }
                        return list.removeLast();
                }
        }
}


答:这里有可能会死锁:当外界调用pop(),但堆栈中没有元素,即list.size() <= 0,Stack进入停滞状态(wait())(注意此时list被锁定了 ,但Stack不会被锁定),此时外界仍然可以进入push()(因为wait()不会锁定Stack),但此时在push()中调用list.addLast()时,因为list 被锁定,所以无法调用。
==================================================================
答案又了,但是怎么修改程序才能避免死锁呢??

郁闷小男人 发表于 2011-9-7 10:12 | 显示全部楼层
为什么方法已经同步了,还要再同步list呢?去掉其中一个即可

木已 发表于 2011-9-7 10:12 | 显示全部楼层
楼上正解,类外线程锁this,类内线程锁list

走就走吧 发表于 2011-9-7 10:13 | 显示全部楼层
list都空了,为什么还要wait?

钰云 发表于 2011-9-7 10:13 | 显示全部楼层
一个丑陋的类

北大青鸟 发表于 2011-9-7 10:13 | 显示全部楼层
Thinking in java 好像有,是wait和notify那一节吧
Java代码  
package com.heyongjin.test;   
  
import java.util.LinkedList;   
  
public class Stack {   
  
    LinkedList list = new LinkedList();   
  
    public void push(Object x) {   
        synchronized (list) {   
            list.addLast(x);   
            list.notifyAll();   
        }   
    }   
  
    public Object pop() throws Exception {     
        synchronized (list) {   
            while(list.size() <= 0) {   
                list.wait();   
            }   
            return list.removeLast();   
        }   
    }   
}  

package com.heyongjin.test;

import java.util.LinkedList;

public class Stack {

        LinkedList list = new LinkedList();

        public void push(Object x) {
                synchronized (list) {
                        list.addLast(x);
                        list.notifyAll();
                }
        }

        public Object pop() throws Exception {  
                synchronized (list) {
                        while(list.size() <= 0) {
                                list.wait();
                        }
                        return list.removeLast();
                }
        }
}


不过用while会多判断一次吧
这样也可以
Java代码  
public Object pop() throws Exception {     
    synchronized (list) {   
                Object result= null;   
        if(list.size() >0) {   
             result= list.removeLast();   
  
        }else{   
             list.wait();   
                }   
                return result;   
    }   
}  

public Object pop() throws Exception {  
        synchronized (list) {
                Object result= null;
                if(list.size() >0) {
                     result= list.removeLast();

                }else{
                     list.wait();
                }
                return result;
        }
}





天上智喜 发表于 2011-9-7 10:13 | 显示全部楼层
把空的判断挪到锁定对象的代码外面来
Java代码  
public synchronized Object pop() throws Exception {   
       if (list.size() <= 0) {      
                wait();      
       } else {      
       synchronized (list) {              
            return list.removeLast();      
       }      
       }   
}   

public synchronized Object pop() throws Exception {
       if (list.size() <= 0) {   
                wait();   
       } else {   
       synchronized (list) {           
            return list.removeLast();   
       }   
       }
}



只学java 发表于 2011-9-7 10:14 | 显示全部楼层
双锁......
有两个锁对像时就有可能死锁

把锁对像变成同一个就可以避免双锁.


shmilyyu 发表于 2011-9-7 10:14 | 显示全部楼层
生活小丑 写道
whiletrue 写道
list都空了,为什么还要wait?

同问

应该是pop方法的目的是要返回一个非空的元素,所以空的时候就要等待。
Jethro 发表于 2011-9-7 10:32 | 显示全部楼层
此贴有意思~  
 楼主| 曾经的小孩 发表于 2011-9-8 17:01 | 显示全部楼层
支持你加分
yoyo 发表于 2011-9-8 17:02 | 显示全部楼层
不是吧~~
您需要登录后才可以回帖 登录 | 成为会员

本版积分规则

QQ|手机版|小黑屋|网站帮助|职业IT人-IT人生活圈 ( 粤ICP备12053935号-1 )|网站地图
本站文章版权归原发布者及原出处所有。内容为作者个人观点,并不代表本站赞同其观点和对其真实性负责,本站只提供参考并不构成任何投资及应用建议。本站是信息平台,网站上部分文章为转载,并不用于任何商业目的,我们已经尽可能的对作者和来源进行了通告,但是能力有限或疏忽造成漏登,请及时联系我们,我们将根据著作权人的要求立即更正或者删除有关内容。

GMT+8, 2024-4-25 07:08 , Processed in 0.137753 second(s), 20 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表