1.1.1. 一、进程和线程的介绍。

1、进程是程序在操作系统中的一次执行过程,是操作系统进行资源分配和调度的基本单位。

2、线程是进程的一个执行实例,是执行程序的最小单元。一个进程可以创建和销毁多个线程。同一个进程中的多个线程可以并发执行

3、一个程序执行时,至少有一个进程;一个进程至少有一个线程。

1.1.2. 二、并发和并行。

1) 多线程程序在单核上运行,就是并发。

并发的线程互相争夺单核CPU的执行时间片段。从微观角度来看,一个时间点只有一个线程在执行。

2) 多线程程序在多核上运行,就是并行。

并行有多核运行,每个时间点线程都同时在执行。

1.1.3. 三、Go 协程和 Go 主线程。

Go 主线程(有程序员直接称为线程/也可以理解成进程): 一个 Go 线程上,可以起多个协程,可以这样理解,协程是轻量级的线程[编译器做优化]。

  • Go 协程的特点。

1) 、有独立的栈空间。

2)、共享程序堆空间。

3)、调度由用户控制。

4)、协程是轻量级的线程。

5)、主线程是一个物理线程,直接作用在 cpu 上的。是重量级的,非常耗费 cpu 资源。

6)、协程从主线程开启的,是轻量级的线程,是逻辑态。对资源消耗相对小。

7)、Golang 的协程机制是重要的特点,可以轻松的开启上万个协程。其它编程语言的并发机制是一般基于线程的,开启过多的线程,资源耗费大,这里就突显 Golang 在并发上的优势了。

1.1.4. 四、协程的例子:

示例如下:

在主线程中,开启一个 goroutine, 该协程每隔 1 秒输出 "hello,world"。在主线程中也每隔一秒输出"hello,golang", 输出 10 次后,退出程序。

// 每隔一秒打印
func Test()  {
    for i := 0; i< 5; i++ {
        fmt.Println("Test .."+strconv.Itoa(i))
        time.Sleep(time.Second)
    }
}

func main() {

    go Test() // 开启一个协程

    for i := 0; i< 5; i++ {
        fmt.Println("---main .."+strconv.Itoa(i))
        time.Sleep(time.Second)
    }
}

执行效果如下:

---main ..0
Test ..0
---main ..1
Test ..1
---main ..2
Test ..2
Test ..3
---main ..3
---main ..4
Test ..4

说明:

1、使用go Test() 开启一个协程,也就是go关键字,后面跟上要执行的代码。

2、主线程必须阻塞,因为主线程执行完成后程序就自动退出了。

如果主线程变成下面这样,就输出不了任何东西。

func main() {
    go Test() // 开启一个协程
}

1.1.5. 五、设置可同时执行的最大CPU数。

go语言1.8版本之前,需要设置一下当前程序可同时执行的最大CPU数,以便高效的利用cpu。

go1.8之后默认让程序运行在多个核上,就不用设置了。

设置CPU的代码如下:使用 runtime 包

func main() {
    // 获取当前系统的逻辑cpu个数
    num := runtime.NumCPU();

    // GOMAXPROCS设置可同时执行的最大CPU数,并返回先前的设置。
    // 若 n < 1,它就不会更改当前设置。本函数在调度程序优化后会去掉。
    runtime.GOMAXPROCS(num-1)

    fmt.Println("cpu个数 =",num); //cpu个数 = 8
}

说明:

1、用 runtime.NumCPU() 获取当前系统的逻辑CPU个数。

2、用 runtime.GOMAXPROCS(num-1)设置当前程序可同时执行的最大CPU数。

results matching ""

    No results matching ""