多线程编程中的本质问题

    在编写多线程程序的时候我们经常需要判断临界条件,如对象池中的可用数,某一个对象是否可用等状态.当我们这么做的时候其实就已经错了,为什么这么说因为在我们的潜意识里一直在使用绝对时间点来判定多线程程序.因为我们习惯性的用锁然后判定当前时间点的临界条件状态并作出相应处理.这样做当然可以但是在理念上错了,锁是为了同步资源用的而不是临界条件(当然你们做也没关系不过我向往无锁并发).那我们不依赖绝对时间点还能依赖什么呢?那就是事件,不过这个event可不是.net里的那个关键字.这是个逻辑上的概念.所谓多线程中的事件是指一定会发生的事情.比如要使用对象池中对象,这就是一个event.那么就会发生而不是依靠判断当前可用数,因为你读取的那一刻可以使用可是调用的时候可能就没有可用的了(当然可以用锁,不过锁的效率实在很低还会死锁).那我们到底怎么处理这个事件呢,在绝大多数情况下使用semaphore(有时可以用InterLocked请看我的"自己实现一个Semaphore "里对2个临界条件的处理).说到这就简单了,我们把对具体条件的判断更改为对semaphore对象的wait.这样就不会出现当临界条件不满足时用while+sleep进行处理的丑陋代码了.

    在我的编程体系里我给semaphore起了个别名叫做Event_Trigger 事件触发器.它的目的就是用来控制一个事件是否可以出发的.比如在多线程编程中生产消费者模型是一个最典型,最常用的模型.所以我们一般都会实现一个生产消费队列.这个queue很简单就是生产者把生产出来的产片放到队列中,而消费者从队列中拿走消费.在日常生活中最直观的例子就是蛋糕店,糕点师把做好的蛋糕放到柜台上供大家购买.这里柜台就是这个queue而这就有一个问题了柜台放满了怎么办?我们可能会说queue嘛可以动态增长的,但是内存也是有限的我们不能让queue无限增长下去.所以我们需要二个临界条件:最大queue数和是否可消费来进行控制.但实际上我们要的是二个事件,生产事件和消费事件,如果事件不能发生就阻塞如此而已.

    下面我们来看看怎么利用事件的机制来编写这个queue,我个人认为比判断绝对时间点的方式更好,更直接(因为这个队列非常简单我只给出关键的代码片断).

Event_Trigger  produce; //最小可用0,最大数为int.max
Event_Trigger _consume; //同上
public void Push(Item i) //生产
{
_produce.Wait();                   //等待生产事件发生
queue.Enqueue(i);
_consume.Post();               //通知消费事件发生
}
Pop方法中使用_consume.Wait(),_produce.Post().

这样是不是很简洁,很直观.我当时在倾听了我boss的讲解以后真是有醍醐灌顶的感觉,上边写的一堆可能没有表述清楚,不过我强烈想大家推荐这种使用事件代替临界条件判断的方式.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值