领导者/追随者(Leader/Follower)

news/2025/2/27 10:28:55

领导者/追随者(Leader/Follower)

1.问题

多线程是实现并发处理多事件的应用程序的一种常用技术。然而,很难实现高性能的多线程服务器应用程序。这些应用程序通常处理大量同时到达的多类型事件。为了有效地处理这种问题,有三个强制条件必须解决:

1)服务请求可以来自为每个已连接的客户机分配的多事件源(如多TCP/IP套接字句柄)。因此,一个关键设计强制条件是在线程和事件源间确定有效的多路分解关联。

2)为了将性能最大化,必须尽量减少引起与并发有关的开销。(如语境切换,同步化和缓存一致性管理)。特别地,为在多个线程间传递的请求动态分配内存的同步模型会在传统的多处理器操作系统中产生巨大的开销。

3)多路分解共享的事件源集合上事件的多个线程必须相互协作,以防止竞争条件。竞争条件可能出现在多个线程试图同时访问或修改某些类型的事件源的时刻。

2.解决方案

构造一个线程池,通过对到达事件源的事件多路分解,并向处理事件的应用服务同步地分配事件,依此轮流进行来共享事件源集合。

详细细节:设计一个线程池机制,允许其中的多个线程相互协作并在检测、多路分解、分配和处理事件时保护临界区。在这种机制中,每次允许一个线程(领导者)等待在事件源集合上出现一个事件。同时,其他线程(追随者)排队等待它们成为领导者的机会。当前的领导者线程从事件源集合检测到一个事件后,它首先将一个追随者线程提升为新的领导者,然后扮演处理线程的角色,对事件多路分解并分配给指定的事件处理程序,在处理线程中实现与应用有关的事件处理。在当前领导者线程在由所有线程共享的事件源集合上等待新的事件时,多个处理线程可以并发地处理事件。在处理完事件后,处理线程恢复到追随者角色,并等待再次成为领导者线程。

3.结构

由操作系统提供句柄,用来区分可以生成事件并将之排队的事件源(如网络连接或打开文件)。事件可以由外部事件源(如从客户机发送一个服务的CONNECT事件或READ事件),或者内部事件源(如超时)引发。句柄集是句柄的集合,可以用来等待一个或多个事件在该句柄集中的句柄上发表。当可以激活句柄集中句柄上的一个操作而不发生操作阻塞时,句柄集返回到它的调用者。

事件处理程序明确了由一个或多个钩子方法组成的接口。这些方法表示可以对发生在句柄上的与应用有关的事件进行处理的操作集。

具体事件处理程序是事件处理程序的特化,并实现应用程序提供的特定服务。特别地,具体事件处理程序实现负责处理从句柄接收的事件的钩子方法。

领导者/追随者模式的核心是线程池。一个或多个线程扮演追随者角色并在线程池同步器上排队等待扮演领导者角色。其中一个线程被选择成为领导者,等待事件在句柄集中的句柄上发生。当有一个事件发生时,当前领导者线程将一个追随者线程提升为新的领导者。原来的领导者接着扮演处理线程的角色,对从句柄集到相应事件处理程序的事件进行多路分解,并分配处理程序的钩子方法进行事件处理。在处理线程完成了事件的处理后,它再次返回扮演追随者线程的角色,在线程池同步器上等待再次成为领导者线程。

4.实现

1)选择句柄和句柄集机制。句柄集是句柄的集合,领导者线程可以用它来等待在事件源集上发生事件。开发者通常选择底层操作系统提供的句柄和句柄集机制,而不是随便地实现它们。

1.1)确定句柄类型。

·并发句柄。这种类型的句柄允许多个线程并发访问事件源的句柄而不会引发可能破坏,丢失或扰乱数据的竞争条件。

·迭代句柄。这种类型的句柄需要多线程迭代访问事件源上的句柄,因为并发访问将导致竞争条件。

1.2)确定句柄集的类型。

·并发句柄集。这种类型的句柄集上可以有并发的动作,例如,线程池对它的并发访问。

·迭代句柄集。这种类型的句柄集在它可以启动句柄集中一个或多个句柄上的一个操作而不阻塞操作时返回到它的调用者。虽然迭代句柄集可以在单个调用中返回多个句柄,但是它一次只能由一个线程调用。

1.3)确定选择某个句柄和句柄集机制的效果。

1.4)实现事件处理程序的多路分解机制。

·对低层操作系统事件多路分解机制编程。在这种策略中,直接使用操作系统提供的句柄集多路分解机制。

·对高层事件多路分解模式编程。在这种策略中,开发者使用诸如反应器、主动器和包装器材外观等高层模式。

2)在句柄集中实现临时激活(停用)句柄的协议。当事件到达时,领导者线程执行以下三步:

·在句柄集中暂时停用该句柄。

·将一个追随者线程提升为新的领导者。

·继续处理事件。

在句柄集中将该句柄停用避免了从选择新领导者到处理事件的时间内出现竞争条件。如果新的领导者在这一段时间内等待句柄集中的同一句柄,那么它可能再次将该事件多路分解,这样做是错误的,因为这时已经在进行分配了。在事件被处理后,句柄在句柄集中被再次激活,这样领导者线程等待事件在该句柄或句柄集中其他激活的句柄上出现。

3)实现线程池。为了将一个追随者线程提升为领导者角色,以及确定哪个线程是当前的领导者,领导者/追随者模式的工具必须管理一个线程池。一种直接的实现方法是简单地将所有追随者线程放入集合,等待单独的同步器,如信号灯和条件变量。在这种设计中,不管是哪个线程来处理事件,只要共享句柄集的池中的所有线程都是串行化的。

4)实现允许线程初次加入(以及以后再次加入)线程池的协议。该协议用于以下两种情况:

·在首创了能获得和处理事件的线程池后。

·以及在处理线程已完成并且可以处理另一个事件时。

如果没有领导者线程可用,则处理线程可以立即变为领导者。如果领导者线程已经获得,一个处理线程可以在线程池同步器上等待变成追随者。

5)实现追随者提升协议。

5.1)实现句柄集同步协议。如果句柄集是迭代的,并且我们盲目地提升了一个新的领导者线程,那么可能新的领导者线程会试图处理与前一个领导者线程检测到的并正在进行处理的同一事件。为了避免这种竞争条件,必须在将一个追随者句柄提升为领导者句柄并将事件分配给具体事件处理程序之前,将该句柄从句柄集的候选句柄中删除。分配并处理事件后,必须从句柄集中再次激活该句柄。

5.2)确定提升协议排序。

·LIFO顺序。在许多应用程序中,下一次提升哪个追随者线程不重要,因为所有线程都是对等的。在这种情况下,领导者线程可以按照后进先出(LIFO)的顺序提升追随者线程。LIFO协议通过确保等待时间最短的线程首先被提升将CPU高速缓存的相似性最大化。

·优先级顺序。在某些应用程序中,特别是实时应用程序中,线程可能运行在不同的优先级上。在这种情况下,需要根据追随者线程的优先级对它们进行提升。这种协议可以使用某些类型的优先级队列实现,如堆。虽然该协议比LIFO协议更复杂,但是为了使优先级反序的情况最少,就需要按照追随者线程的优先级对它们进行提升。

·由实现定义的顺序。在使用操作系统同步器(如信号灯或条件变量)来实现句柄集时常用这种顺序,通常按照由实现定义的顺序分配等待线程。这种协议的优点是它能高效地映射到本地操作系统同步器上。

6)实现事件处理程序。

5.结论

优点:

1)性能增加。

·增强了CPU高速缓存相似性并消除了动态内存分配和线程间共享的数据缓冲区要求。

·通过在线程间不交换数据的方法来使加锁开销达到最小,因此降低了线程同步化。

·可能将优先级逆序的数量减少到最小,因为服务器中没有进行其他排队。

·不需要语境切换以处理每个事件,减少了事件分配延时。

2)编程简单性。领导者/追随者模式简化了并发模型的编程,其中多线程可以使用共享句柄集接收请求,处理响应并多路分解连接。

不足:

1)实现复杂性。

2)缺乏灵活性。

3)网络I/O瓶颈。


http://www.niftyadmin.cn/n/3653112.html

相关文章

今天遇到两个问题:Can't connect to MySQL server 与 Access denied for user !

问题一:本机(localhost)连接一切正常,但是无法从其他电脑上登入 MySQL 数据库! 下面是 /etc/mysql/my.cnf 中的一段摘录:# Instead of skip-networking the default is now to listen only on# localhost w…

FreeBSD-STABLE 居然是开发用的分支,我一直搞错了好多年...!

我一直认为对于FreeBSD的系统来说&#xff0c;发行版的稳定性是&#xff1a;CURRENT < RELEASE < STABLE&#xff0c;所以在灌完系统后立刻 cvsup 到对应的 STABLE 版本去... 这几天刚好碰到 Pengfei 也在看 FreeBSD 的 cvsup 管理部分&#xff0c;他正在疑惑生产系统上面…

值得读两遍的图书

值得读两遍的一些纯技术类图书&#xff1a;《设计模式》《重构》《J2EE without EJB中文版》 《Ajax实战》《Ajax模式与最佳实践》《Ajax设计模式》值得读两遍的一些非纯技术类图书&#xff1a;《人月神话》《人件》《UML精粹》《编写有效用例》《解析极限编程——拥抱变化》《…

建立国内Web前端开发的生态系统

在2003年年初&#xff0c;因为朋友许恩良的缘故&#xff0c;我来到了上海和为科技有限公司工作。公司的创始人是赖毅&#xff0c;他也曾经是开发人员出身&#xff0c;有着非常丰富的开发经验。赖毅是一个喜欢自出机杼的人&#xff08;这样的人一般都是某一方面的高手&#xff0…

做事情的快与坚持

其实我是一个很急躁的人&#xff0c;总是希望把事情尽快做完。每次出门办事的时候都在想如何把几件事情放在一起来做。但是很多时候&#xff0c;碰到一些疑难问题&#xff0c;总是没有办法快速完成。我总是感觉别人比我做事情要快&#xff0c;所以总是有着一种严重的危机感。读…

Redis 命令参考手册

Redis 命令参考手册 好资料&#xff1a; http://redis.readthedocs.org/en/latest/

linux无锁化编程--__sync_fetch_and_add系列原子操作函数

linux支持的哪些操作是具有原子特性的&#xff1f;知道这些东西是理解和设计无锁化编程算法的基础。 下面的东西整理自网络。先感谢大家的分享&#xff01; __sync_fetch_and_add系列的命令&#xff0c;发现这个系列命令讲的最好的一篇文章&#xff0c;英文好的同学可以直接去…

开始翻译Fielding的博士论文

Fielding是HTTP1.1和URI标准的主要制定者 。他在2000年写了一篇博士论文&#xff0c;提出了REST的架构风格和设计思想。http://www.ics.uci.edu/~fielding/pubs/dissertation/top.htm今天REST被众多RIA技术广泛采用&#xff0c;作为设计开发RIA应用的最佳的架构风格。我们已经获…