• 第五部分-并发编程模型3:协程


    1.协程

    轻量级线程
    Coroutine

    线程是内核态调度的,协程是用户态调度的,用户态调度的资源消耗更小,性能更高
    内核态用户态之间切换有成本
    线程的栈大小:1M
    协程的栈大小:几K或者几十K

    2.Golang中的协程示例

    
    import (
      "fmt"
      "time"
    )
    func hello(msg string) {
      fmt.Println("Hello " + msg)
    }
    func main() {
        //在新的协程中执行hello方法
      go hello("World")
        fmt.Println("Run in main")
        //等待100毫秒让协程执行结束
      time.Sleep(100 * time.Millisecond)
    }
    

    3.Golang中应用Thread-Pre-Message模式

    一个请求,开一个协程

    
    import (
      "log"
      "net"
    )
    
    func main() {
        //监听本地9090端口
      socket, err := net.Listen("tcp", "127.0.0.1:9090")
      if err != nil {
        log.Panicln(err)
      }
      defer socket.Close()
      for {
            //处理连接请求  
        conn, err := socket.Accept()
        if err != nil {
          log.Panicln(err)
        }
            //处理已经成功建立连接的请求
        go handleRequest(conn)
      }
    }
    //处理已经成功建立连接的请求
    func handleRequest(conn net.Conn) {
      defer conn.Close()
      for {
        buf := make([]byte, 1024)
            //读取请求数据
        size, err := conn.Read(buf)
        if err != nil {
          return
        }
            //回写相应数据  
        conn.Write(buf[:size])
      }
    }
    
    

    4.协程实现异步转同步

    在 Java 里使用多线程并发地处理 I/O,基本上用的都是异步非阻塞模型,这种模型的异步主要是靠注册回调函数实现的,那能否都使用同步处理呢?显然是不能的。因为同步意味着等待,而线程等待,本质上就是一种严重的浪费。不过对于协程来说,等待的成本就没有那么高了,所以基于协程实现同步非阻塞是一个可行的方案。

    同步非阻塞代码范例,来源于openresty

    
    -- 创建socket
    local sock = ngx.socket.tcp()
    -- 设置socket超时时间
    sock:settimeouts(connect_timeout, send_timeout, read_timeout)
    -- 连接到目标地址
    local ok, err = sock:connect(host, port)
    if not ok then
    -  -- 省略异常处理
    end
    -- 发送请求
    local bytes, err = sock:send(request_data)
    if not bytes then
      -- 省略异常处理
    end
    -- 读取响应
    local line, err = sock:receive()
    if err then
      -- 省略异常处理
    end
    -- 关闭socket
    sock:close()   
    -- 处理读取到的数据line
    handle(line)
    
    原创:做时间的朋友
  • 相关阅读:
    jmeter 创建
    MySQL远程连接不上的解决方法
    删除文件及文件夹
    wsdl使用方式
    solr查询参数过长问题解决
    Inno Setup添加自定义页面
    java中日期的加减,比较,以及与String的互相转换
    vue项目引入第三方js
    vue覆盖elementui样式的几种方式
    SQL Server 连接表内部查询中的逗号分隔字符串
  • 原文地址:https://www.cnblogs.com/PythonOrg/p/14919811.html
Copyright © 2020-2023  润新知