一、线程和分布式的通信
随着技术的不断发展,多线程和分布式通信愈发的普及。那么在这种场景下的如何进行数据的通信,便成为了一个非常典型的问题。无论是多线程还是分布式,其实其抽象出来的通信机制都是类似的。或者说换句话,多线程和分布式被普及的原因是一样的,那就是如何解决大数据量的快速交互,即解决生产者和消费者的问题。
这种通信机制有很多种,在前面也分别的进行过阐述,比如常见的事件、管道、网络、消息等等。这些通信机制,各有各的优点和适用场景,当然也存在着各种各样的问题和缺点。这就需要开发者能够灵活的综合运用这些技术来解决问题。
二、生产者和消费者的平衡
回到最常见的生产者消费者的问题,即生产队列和消费队列的最优的动态平衡。生产者的线程和消费者的线程要匹配,既不能生产的过多,导致消费队列的积压甚至因此而崩溃,也不能因为生产者的产出太少,导致消费者队列的等待。
一般在这种情况下,可能很多开发者会选择使用线程同步来解决问题,也可能会使用一些消息框架来解决这类问题。可同步带来的性能损失,如何降低到最低?那如果使用无锁编程呢?会不会带来效率的显著提升?
三、问题和解决
从上面的分析可以判断出,其实无论哪种方式,都需要处理同步的粒度的问题。举一个简单的例子,一个生产者和一个消费者,生产者在把消息压入队列后就进行一个同步的通知(不管是使用事件还是条件变量等),还是等到某种条件下再进行同步通知效率更高呢?也就是说,不用每次生产后都进行通知,而在某种情况下才会通知。由于同步事件的通知会导致线程的切换和上下文的处理,所以基本上可以判定,后者会更优。但优多少需要实际的场景进行验证。只是从理论上看,这种情况是占有优势的。
在无锁队列中,如果生产者速度比较慢,消费者比较快,CAS的原理是占用CPU进行自旋等待,那设计上肯定不能让消费者没事总那儿旋转占用着CPU,一般会有一个机制在多长时间后进行等待机制让出CPU。或者在突传情况下,CAS自旋就非常有意义,但在突传过后,CAS一定要让出CPU。所以就可以基本得出一个结论,在消费者让出CPU休眠时,再进行同步通知进行唤醒,此时的效果肯定是最佳的。
这种机制不光是推理出来,在实践中也是如此,比如使用一些开源框架中即是进行这样设计的。一些开源的无锁队列,经过测试发现,连续通知和休眠后通知,其实效率还是差不少的。这也是一个非常明显的例证。
那么如何进行线程间状态的判断呢?这个有很多种方法,一般来说可以设置一个双方都需要读写操作的变量,而CAS正是擅长对这种固定值的判断的,通过固定值与队列间的某种特定的条件,即可判断互相的状态。
四、总结
其实队列的处理,不光有这种细节需要处理,包括内存大小的处理,是否提前处理,都是需要考虑的。正如前面所说,一个队列的设计,不仅仅是一个算法的问题,可能涉及到很多的技术知识和相关的难点。如何能够综合运用这些知识适配开发场景,就是对设计师的一个考验了。