1.为什么C语言较Python等脚本语言编写计算密集型任务效率更高,而Python等脚本语言编写IO密集型任务较C语言效率更高?
答:可能的解释a:IO密集型任务比如WEB服务,这类服务的开发代码可能会经常性的更改、更新,所以需要开发效率较高的代码,即代码量少,码起来较快。
2.在进行TCP编程,调用socket进行通信时,客户端发送数据出去,一定会等到服务器传送数据回,才会接着执行后面的代码吗?
答:这是同步IO模型。异步IO模型便能有效解决这个问题,使得主线程在等待一个IO操作返回结果的过程中,能继续执行下面的代码。
3.在异步IO模型下,一个线程就可以同时处理多个IO请求,并且没有切换线程的操作。对于大多数IO密集型的应用程序,使用异步IO将大大提升系统的多任务处理能力。为什么一个线程处理多个IO请求时并没有切换线程的操作,那它又是如何进行多个IO请求的处理呢?
答:利用协程,使用yield关键字将协程标记为generator,在执行多协程(共享一个线程)时,便能利用yield的中断及返回值实现协程之间的切换操作,从而实现异步IO。
4.yield表达式如何理解其执行机制?
答:运行如下代码:
def consumer():
r = ''
while True:
print(r)
n = yield r
if not n:
return
print('[CONSUMER] Consuming %s...' % n)
r = '200 OK'
def produce(c):
c.send(None)
n = 0
while n < 5:
n = n + 1
print('[PRODUCER] Producing %s...' % n)
r = c.send(n)
print('[PRODUCER] Consumer return: %s' % r)
c.close()
c = consumer()
produce(c)
结果为:
#空行
[PRODUCER] Producing 1...
[CONSUMER] Consuming 1...
200 OK
[PRODUCER] Consumer return: 200 OK
[PRODUCER] Producing 2...
[CONSUMER] Consuming 2...
200 OK
[PRODUCER] Consumer return: 200 OK
[PRODUCER] Producing 3...
[CONSUMER] Consuming 3...
200 OK
[PRODUCER] Consumer return: 200 OK
[PRODUCER] Producing 4...
[CONSUMER] Consuming 4...
200 OK
[PRODUCER] Consumer return: 200 OK
[PRODUCER] Producing 5...
[CONSUMER] Consuming 5...
200 OK
[PRODUCER] Consumer return: 200 OK
分析可发现:凡send(mesg)方法即执行相应generator函数并把mesg赋给当前yield表示式,然后直至遇到下一个yield关键字(如后面无yield,则需.close(),否则会抛出StopIteration异常),并返回下一个yield的参数(此例中为r)。
c.send(None)初始化即从函数开始执行,传入None是因为最开始没有yield表达式接收赋值,然后直到遇到yield(1号),并返回yield的参数r(为' '),亦跳出consumer函数,回到produce函数中继续执行下面的代码;
遇到c.send(n)又开始切换到consumer中执行,从上次中断处执行即yield处,将n赋值给本次yield(1号)表达式,然后继续执行consumer中下面的代码,直至遇到下一次yield(2号),返回yield(2号)的参数r,中断consumer,切换produce函数,接着send(n)继续执行;如此循环,直至produce结束。
总结:有yield表达式的执行方式即是利用c.send(mesg)切换到c函数中执行,
遇到yield表达式,将mesg赋值给yield表达式,继续执行c函数,
并在下一次yield中断c函数的执行,并将此时yield的参数r作为c.send(mesg)的返回值,回到c.send(mesg)所在的代码处执行下面的代码,
再下一次c.send(mesg)从中断的yield处执行c函数。