贝网博客

我的分类
流水记事
源码下载
Asp.net
其它
数据库
Javascript
.Net技术
我的相册
友情链接
博客园
CSDN博客
Start0
最新回复
嗷嗷的cCC
fasdfasdf
[:..
lz这个东西好厉害,我..
哈哈,好照片
不错,以前一直用黄色..
终于找到支持ff的修正..
终于找到支持ff的修正..
新鲜性
看看,试试,好不好使。
分类 =》.Net技术
一个简单的并发问题及修改方案
发表于:2012-02-02 18:41:37
更新于:2012-02-17 16:42:10

类定义:
01、public class Teacher{// 老师类
02、private List<Student> _students;
03、    public List<Student> Students{// 这个老师的学生列表
04、        get{
05、            if(_students == null){
06、                _students = new List<Student>();
07、                // 这里是添加学生清单的逻辑
08、                _students.Add(new Student());
09、            }
10、            return _students;
11、        }
12、    }
13、}
上面的这段代码应该没啥问题,应该是在单线程访问Students属性时没有问题,在并发的时候,
比如有a、b两个用户同时访问这个属性,就会出现
a执行到第7行时,b用户进来了,执行到第5行,发现_students不为null,就直接return了,导致b用户得到的学生清单为0个

解决方案1:把get方法进行lock,只允许单线程进入,如:
public class Teacher{// 老师类
private List<Student> _students;
    public List<Student> Students{// 这个老师的学生列表
        get{
            if(_students == null){
                lock(_students){
                    if(_students == null){// 再判断一次,避免进入时已经被别的线程填充过,导致重复填充
                        _students = new List<Student>();
                        // 这里是添加学生清单的逻辑
                        _students.Add(new Student());
                    }
                }
            }
            return _students;
        }
    }
}
这个方案的缺点在于lock会导致所有的线程堵住,都要等待第一个线程的完成,其余线程才能继续

解决方案2:
public class Teacher{// 老师类
private List<Student> _students;
    public List<Student> Students{// 这个老师的学生列表
        get{
            if(_students == null){
                var tmp = new List<Student>();
                // 这里是添加学生清单的逻辑
                tmp.Add(new Student());
                _students = tmp;
            }
            return _students;
        }
    }
}
这个方案的缺点在于,首次访问Students属性时,由于瞬间_students为null,进入的所有线程都会去填充一遍_students,重复工作,如果这个填充时间短,还无所谓,如果比较长,建议使用方案1

发表评论
名称(*):
邮箱:
正文:

©2008 Beinet.cn 版权所有