Channel和synchronized关键字

June 22, 2013 · One minute read

使用Go语言的Channel和GoRoutine可以实现很多需要线程同步的功能,比如说Java中synchronized关键字。通常使用synchronized是为了线程安全,防止读写冲突,并非所有的情况都需要同步。比如说在Lucene的SegmentCoreReaders中对关闭事件监听的功能中,添加和删除监听器的动作并不需要强制同步,而关闭事件的触发,也不需要同步进行。使用异步单Actor模式能够很好地防止读写冲突,同时减少同步带来地开销。

但是这种机制也存在缺点。GoRoutine默认是在单线程上运行的,虽然Go语言本身在诸如Sleep和IO操作中主动让出CPU控制权,但是本质上感觉和Java一样,都是非抢占式线程调度。结果就是,如果前面的GoRoutine没有运行完毕,那么后面的用来避免读写冲突的异步Actor也无法被调用。至于GoRoutine内部有没有优先级,这个我暂时还不清楚。

所以对于真正需要同步的操作,还是应该使用锁。而那些可以异步执行,同时对实时性要求不高(至少没有副作用)的功能,可以通过Channel和GoRoutine来实现。