导航

    蓝鲸ROS机器人论坛

    • 注册
    • 登录
    • 搜索
    • 版块
    • 话题
    • 热门
    ROS交流群
    ROS Group
    产品服务
    Product Service
    开源代码库
    Github
    官网
    Official website
    技术交流
    Technological exchanges
    激光雷达
    LIDAR
    ROS教程
    ROS Tourials
    深度学习
    Deep Learning
    机器视觉
    Computer Vision

    线程和协程

    技术交流
    1
    1
    3681
    正在加载更多帖子
    • 从旧到新
    • 从新到旧
    • 最多赞同
    回复
    • 在新帖中回复
    登录后回复
    此主题已被删除。只有拥有主题管理权限的用户可以查看。
    • weijiz
      weijiz 最后由 编辑

      在写程序的时候为了提高执行效率经常会用到线程.把任务分配到不同的线程里面同时执行,这样即使其中一个被阻塞了,程序还是可以运行,程序运行效率得到了很大的提高.线程是一个经常用到的概念这里就不多说了.

      但是随着大家使用的线程越来越多,线程的劣势就越来越明显了.最有名的就是c10k问题.c10k问题是在写服务器程序时遇到的.如何使一个服务器同时和10K个客户端保持网络连接?一般的做法是给每个连接开一个独立的线程,但是这样就会有上万个线程.大量的资源被浪费在线程的管理上.线程已经无法再胜任这个任务了.

      在javascript中处理异步问题的方式给了我们很好的思路.javascript程序是单线程的,也就是某一时刻只能有一个程序在运行.但是javascript却可以很好的处理异步问题.下面以一个读取文件的例子来说明

      var fs = require('fs'); //引入文件处理库 fs
      fs.readFile('/etc/passwd', (err, data) => {
        if (err) throw err;
        console.log(data);
      });
      console.log("I'm not blocking");
      

      readFile函数的第一个参数是文件路径, 第二个参数是回调函数.当文件读取完成或者失败的时候回调函数会被执行.
      这样当程序运行到readFile的时候就不会被阻塞.也就是说在文件读取完成之前就会在终端中显示出I'm not blocking
      这是怎么实现的呢?
      这是因为javascript有一个叫做Event loop的线程,专门用来监控事件有没有触发,如果触发就调用相应的回调函数.比如说上面的readFile函数,实际上是相当于在Event Loop里面注册了一下.

      这就是协程的概念.用一个主线程去完成各种异步操作.看起来好像各自都有自己独立的线程一样.

      具体怎么实现一个协程呢?我们可以用python从头开始搭建出来.

      在python中有一种叫做generator的东西.比如 a = xrange(0,100000)这里a就是一个generator.一般使用时会觉得a是一个list.但是不是这样的.a中的元素只有在被使用到的时候才会被生成.

      def test():
          for i in range(0,10):
              yield i
      a = test() # a就是一个generator
      a.next() # 返回1
      a.next() # 返回2
      a.next() # 返回3
      # 直到10
      a.next() # 抛出 StopIteration 异常
      

      这样a就可以用来表现协程的状态.在Event Loop之中不停的执行协程返回的generator直到这个generator返回StopIteration为止,再执行对应的回调函数.

      class Defer:
          def __init__(self):
              self.waitFlag = True
              self.results = None
      
          def resolve(self, results):
              self.results = results
              self.waitFlag = False
      
          def get_status(self):
              while self.waitFlag:
                  yield True
      
      def code1():
          mDefer = Defer()
          # start a new thread, and do some time consuming works
          # when the work is complete
          mDefer.resolve(results)
          return mDefer
      
      def code2():
          mDefer = Defer()
          # start a new thread, and do some time consuming works
          # when the work is complete
          mDefer.resolve(results)
          return mDefer
      
      eventList = []
      eventList.append(code1())
      eventList.append(code2())
      while True:
          for event in eventList:
              try:
                  event.get_status()
              except:
                  results = event.results
      
      

      个人感觉原理上就是如此了.

      实际上python中协程的用法

      为了方便使用,python把协程相关的东西做成了asyncio库.并且在python 3.5之中增加了await, async关键字(和C#学的)

      一个用协程的Hello World例子

      import asyncio
      eventloop = asyncio.new_event_loop()
      asyncio.set_event_loop(eventloop)
      async def helloWorld():
          await asyncio.sleep(10)
          print("Hello World")
      eventloop.run_until_complete(helloWorld()) # 这一句是阻塞的,要等待目标任务完成才会执行下面的程序
      print("I'm blocking")
      

      更详细的关于python的协程信息可以看这里

      不过个人感觉python的协程还是不是很自然.没有C#做的好.这个应该是python语言自身的限制造成的.

      1 条回复 最后回复 回复 引用 0
      • 1 / 1
      • First post
        Last post
      Copyright © 2015-2023 BlueWhale community