Go语言的并发编程

Go语言并发编程

  1. Goroutine的使用:

    在函数或方法调用前面加上关键字go,将会同时运行一个新的Goroutine。

  2. 在使用子协程时,要确保每个子协程都能正常运行。

    因为子协程的异常退出会将异常传播到主协程,会直接导致主协程也跟着挂掉,然后整个程序崩溃了。

  3. recover是Go语言的一个内建函数,可以让进入宕(dang第四声)机流程中的goroutine恢复过来,recover仅在延迟函数defer中有效。

    如果当前的goroutine陷入恐慌,调用recover可以捕获到panic的输入值,并且恢复正常的执行。

  4. 并发:把任务在不同的时间点交给处理器进行处理。

    ​ 在同一时间点,goroutine任务并不会同时运行。

    并行:把每一个任务分配给每一个处理器独立完成。

    ​ 在同一时间点,任务一定是同时运行的。

  5. 创建通道只有一种语法,使用make函数。有两种通道类型:

    • 缓冲型通道;var bufferedChannel=make(chan int(类型),1024)
    • 非缓冲型通道。var unbufferedChannel=make(chan int)
    ch <- x  //a send statement
    x = <-ch  //a receive expression in an assignment statement
    <-ch  //a receive statement; result is discarded
    
  6. 通道语法<- 一次只能读写一个元素。

    通道作为容器,可以像切片一样,使用cap()和len()全局函数来获取容量和元素个数。

  7. 通道满了,写操作就会阻塞,协程就会进入休眠,直到有其它协程读通道挪出了空间,协程才会被唤醒。如果有多个协程的写操作都阻塞了,一个读操作只会唤醒一个协程。

  8. Go语言的通道像文件一样,支持读写操作和关闭。

    读取一个已经关闭的通道会立即返回通道类型的“零值”。

    而写一个已经关闭的通道会抛异常。

    如果通道里的元素是整型的,读操作是不能通过返回值来确定通道是否关闭的。

  9. 使用内置sync包提供的WaitGroup对象,使用计数来等待指定事件完成。(多人写入)

  10. 非阻塞读写:当select语句所有通道都不可读写时,如果定义了default分支,那就会执行default分支逻辑,这样就起到了不阻塞的效果。

  11. 竞态检查工具是基于运行时的代码检查,不是通过代码的静态分析来完成的。

    这就意味着那些没有机会运行到的代码逻辑中如果存在安全隐患,它是检查不出来的。

    需要加上-race来执行,如:go run -race 文件名.go

  12. sync.Mutex是一个结构体对象,这个对象在使用过程中要避免被复制----浅拷贝。

    复制会导致锁被分裂了,也就起不到保护的作用了。

    所以在平时的使用中要尽量使用它的指针类型。

  13. defer语句总是要推迟到函数尾部运行,

    所以如果函数逻辑运行时间比较长,会导致锁持有的时间较长,

    此刻使用defer语句释放锁未必是一个好主意。

  14. 在结构体中,外部结构体可以自动继承匿名内部结构体的所有方法。

  15. sync包除了提供互斥锁Mutex(包括Lock()和Unlock()两个常用方法),

    还提供读写锁对象RWMutex

    (包括写加锁Lock()、写释放锁Unlock()、读加锁Rlock()以及读释放锁()四个常用方法)。

    写锁是排他锁,加写锁时会阻塞其它协程再加读锁和写锁;

    读锁是共享锁,加读锁还可以允许其它协程再加读锁,但是会阻塞加写锁。

  16. sync.Once.Do(f func()),能保证sync.Once块只会执行一次,无论是否更换Once.Do(...)。

1. 线程休眠sleep()(1)sleep(时间)指当前线程阻塞的毫秒数;(2)sleep存在异常InterruptedException;(3)sleep时间达到后线程进入 ...