loop_in_codes

低调做技术__欢迎移步我的独立博客 codemaro.com 微博 kevinlynx

半同步半异步模式以及Leader_Follwer模式

这里提到的两个设计模式都是用于高并发系统(例如一个高性能的网络服务器)的。这里我只是简单地提一下:

1.半同步/半异步(half-sync/half-async):

在网上一份资料中引用了一本貌似很经典的书里的比喻:

许多餐厅使用 半同步/半异步 模式的变体。例如,餐厅常常雇佣一个领班负责迎接顾客,并在餐厅繁忙时留意给顾客安排桌位,
为等待就餐的顾客按序排队是必要的。领班由所有顾客“共享”,不能被任何特定顾客占用太多时间。当顾客在一张桌子入坐后,
有一个侍应生专门为这张桌子服务。

按照另一份似乎比较权威的文档的描述,要实现半同步/半异步模式,需要实现三层:异步层、同步层、队列层。因为很多操作
采用异步方式会比较有效率(例如高效率的网络模型似乎都采用异步IO),但是异步操作的复杂度比较高,不利于编程。而同步
操作相对之下编程要简单点。为了结合两者的优点,就提出了这个模式。而为了让异步层和同步层互相通信(模块间的通信),系
统需要加入一个通信队列。异步层将操作结果放入队列,同步层从队列里获取操作结果。

回过头来看看我之前写的那个select网络模型代码,个人认为基本上算是一个半同步半异步模式的简单例子:Buffer相当于通信
队列,网络底层将数据写入Buffer,上层再同步地从该队列里获取出数据。这样看来似乎也没什么难度。 = =

关于例子代码,直接引用iunknown给的:

//这就是一个典型的循环队列的定义,iget 是队列头,iput 是队列尾</STRONG>  
int clifd[MAXNCLI], iget, iput;   
int main( int argc, char * argv[] )  
{  
  ......  
  int listenfd = Tcp_listen( NULL, argv[ 1 ], &addrlen );  
  ......  
  iget = iput = 0;  
  for( int i = 0; i < nthreads; i++ ) {  
    pthread_create( &tptr[i].thread_tid, NULL, &thread_main, (void*)i );  
  for( ; ; ) {  
    connfd = accept( listenfd, cliaddr,, &clilen );  
    clifd[ iput ] = connfd;     // 接受到的连接句柄放入队列</STRONG>  
    if( ++iput == MAXNCLI ) iput = 0;    
  }  
}  
void * thread_main( void * arg )  
{  
  for( ; ; ) {  
    while( iget == iput ) pthread_cond_wait( ...... );  
    connfd = clifd[ iget ];     // 从队列中获得连接句柄</STRONG>  
    if( ++iget == MAXNCLI ) iget = 0;  
    ......  
    web_child( connfd );  
    close( connfd );  
  }  

2.领导者/追随者(Leader/Followers):

同样,给出别人引用的比喻:

在日常生活中,领导者/追随者模式用于管理许多飞机场出租车候车台。在该用例中,出租车扮演“线程”角色,排在第一辆的出
租车成为领导者,剩下的出租车成为追随者。同样,到达出租车候车台的乘客构成了必须被多路分解给出租车的事件,一般以先进
先出排序。一般来说,如果任何出租车可以为任何顾客服务,该场景就主要相当于非绑定句柄/线程关联。然而,如果仅仅是某些
出租车可以为某些乘客服务,该场景就相当于绑定句柄/线程关联。

其实这个更简单,我记得<unix网络编程>中似乎提到过这个。总之有一种网络模型(connection-per-thread?)里,一个线程用于
accept连接。当接收到一个新的连接时,这个线程就转为connection thread,而这个线程后面的线程则上升为accept线程。这里,
accept线程就相当于领导者线程,而其他线程则属于追随者线程。

iunknown 的例子代码:

int listenfd;  
int main( int argc, char * argv[] )  
{  
  ......  
  listenfd = Tcp_listen( NULL, argv[ 1 ], &addrlen );  
  ......  
  for( int i = 0; i < nthreads; i++ ){  
    pthread_create( &tptr[i].thread_tid, NULL, &thread_main, (void*)i );  
  }  
  ......  
}  
void * thread_main( void * arg )  
{  
  for( ; ; ){  
    ......  
    // 多个线程同时阻塞在这个 accept 调用上,依靠操作系统的队列</STRONG>  
    connfd = accept( listenfd, cliaddr, &clilen );  
    ......  
    web_child( connfd );  
    close( connfd );  
    ......  
  }  

posted on 2008-06-04 10:40 Kevin Lynx 阅读(8816) 评论(5)  编辑 收藏 引用 所属分类: network模块架构

评论

# re: 半同步半异步模式以及Leader_Follwer模式 2008-09-12 09:28 littlewater

对两个的名字挺敬畏的——
1. 上面那个应该是常见的网络缓冲吧,网络几个线程收发,触发不同的监听事件然后异步处理这些网络消息;
2. 线程池
自己的理解,觉得不对可批=v=+  回复  更多评论   

# re: 半同步半异步模式以及Leader_Follwer模式 2008-09-12 09:39 Kevin Lynx

@littlewater
我感觉更多地是对线程的描述吧?  回复  更多评论   

# re: 半同步半异步模式以及Leader_Follwer模式 2008-09-12 20:29 littlewater

偶不习惯术语,没办法,是门外汉呢^^  回复  更多评论   

# re: 半同步半异步模式以及Leader_Follwer模式 2010-01-22 18:45 GodPig

这个好……

很清晰~~~  回复  更多评论   

# re: 半同步半异步模式以及Leader_Follwer模式 2015-01-04 10:34 fang_xx

for( int i = 0; i < nthreads; i++ ) {
pthread_create( &tptr[i].thread_tid, NULL, &thread_main, (void*)i );

少了右大括号  回复  更多评论   


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   博问   Chat2DB   管理