原文链接
(四)一些问题的讨论
前面几章的内容都是服务的一些通用的编写原理,但里面隐含着一些问题,编写简单的服
务时看不出来,但遇到复杂的应用就会出现一些问题,所以本章就是用来分析、解决这些问题
的,适用于高级应用的开发人员。我这一章的内容都是经过实验得到的,很有实际意义。
我在第一章里面就说过,是由一个服务的主线程执行 !"# 函数,它将收到各种控
制命令,但是真正处理命令,执行操作的是 $% 的线程。现在,当一个
$&'()!&!*+,'*-$,*. 到达之后,你作为一个开发者,要怎样停止这个服务?在我看过
的一些源代码里,大部分只是简单的调用 ,,# 函数去强行杀掉服务进程。但应
该稍稍有点线程编程的常识就应该知道 ,,# 函数是可用的调用中最为糟糕的一
个,服务线程将得不到任何机会去做应该的清理工作,诸如清除内存、释放核心对象,/ 也
得不到任何线程已经被毁的通知。
所以停止服务的适当方法是以某种方式激活服务线程,让它停止继续提供服务功能,然后
执行完当前操作和清除工作后返回。这就表示你必须在 !"# 线程和 $% 线
程之间执行适当的线程通信。现在已知的最好的内部线程通信机制是 )*!
.()*0完成端口1,假如你编写的是一个大型的服务,需要同时处理为数众多的请求,并且
运行在多处理器系统上面,这个模型就可以提供最佳的系统性能。但也正因为它的复杂性较高,
在小规模的应用上面不值得花费很多的时间和精力,这时作为开发者可以适当的选取其它的通
信方式,诸如异步过程调用队列、套接字和窗口消息,以适应实际情况。
开发服务时的另外一个重要问题就是调用 $$$2 函数时的所有状态报告问题。
很多的服务开发者为了在什么时候调用 $$$2 的问题而常常产生争论,一般推荐
的方法就是:先调用 $$$2 函数,报告 $&'()!&$,*..&+/)+3 状态,然后
将控制代码传给服务线程或者再建立一个新的线程,让它去继续执行操作,当该线程即将执行
完操作之前,再由它将服务的状态设置成 $&'()!&$,*..&/,然后服务正好停止。
上面的主意从两个方面来讲还是很不错的。首先服务可以立即确认收到了控制代码,并将
在它认为适当的时候进行处理;然后就是因为前面说过的,执行 !"# 函数的是主线程,
如果按照这种工作方法,!"# 函数可以迅速的返回,不会影响到其它服务可能收到的
控制请求,对含有多个服务的程序来说,响应各个服务的控制代码的速度会大大的提高。可是,
随之而来的是问题——race condition0即“竞争条件”的产生。
摆在下面的就是一个竞争条件的例子,我花了一点时间来修改我的基本服务的代码,意图
故意引发“竞争条件”的发生。我添加了一个线程,!"# 函数的线程在收到请求后立刻
作出反应,将当前的服务状态设置成“请求正在被处理”即.&+/)+3,然后由我添加的线程
在睡眠了 秒之后再将服务状态设置成“请求已完成”状态——以模拟服务正在处理一些不可中
止的事件,只有处理完成后才会更改服务的状态。一切就绪之后,我尝试在短时间内连续发送
两个“暂停”请求,如果“竞争条件”不存在的话应该只有先发送的那个请求能够到达 $!%,而另
一个则应该返回请求发送失败的信息,天下太平。
事实上很不幸的,我成功了。当我在两个不同的“命令提示符”窗口分别同样的输入下面的
命令:
2
评论1