进程:进程是程序在操作系统中的一次执行过程,系统进行资源分配和调度的一个独立单位
线程:线程是进程的一个执行实体,是CPU调度和分配的基本单位,是比进程跟小的能独立运行的基本单位
进程与线程的关系:一个进程一颗创建和撤销多个线程,同一个进程中的多个线程之间可以并发执行
协程:独立的栈空间,共享堆空间,调度由用户自己控制,本质上优点类似用户级线程,这些用户线程的调用也是自己实现的
协程和线程的关系:一个线程可以跑多个协程,协程是轻量级线程
并发:同一时间段内执行多个操作
并行:同一时刻执行多个操作
Gorouteine多线程:线程是有操作系统进行管理,处于内核态,线程之间进行切换需要发生用户态到内核态的切换
当系统中运行大量线程,系统会变得非常慢,用户态的线程支持大量线程的创建,也叫协程或者goroutine
//创建goroutine
func hello() {
fmt.Println("hello goroutine")
}
func main() {
go hello()
fmt.Prinln("main thread terminate")
time.Sleep(time.Second) //goroutine会随着主线程的结束而结束,需要等待1s
}
//启动多个goroutine
func hello(i int) {
fmnt.Println("hello goroutine",i)
}
func test() {
for i := 0<10;i++{
go hello(i)
}
}
func main() {
test()
time.Sleep(time.Second)
}
//多核控制
var i int
func calc() {for {i++)}
func main() {
cpu := runtime.NumCPU() //显示当前CPU有多少核
fmt.Prinln("cpu",cpu)
runtime.GOMAXPROCS(1) //只允许调用一个cpu内核
for i := 0;i<10;i++ {
go calc()
}
time.Sleep(time.Hour)
}
概念:一个操作系统线程对应用户态多个goroutine,可同时使用多个操作系统线程,操作系统线程对goroutine是多对多关系
调度:当操作系统线程需要执行时,开始逐个执行goroutine
蓝色goroutine执行结束后再执行灰色,当前有两个线程在执行
系统调用的处理

import (
"fmt"
"time"
"sync"
)
var m make(map[int]uint64)
type tesk struct {
n int
}
func calc(t *task) {
var sum uint64
sum = 1
for i := 1;i<t.n;i++ {
sum *= uint64(i)
}
lock.Lock()
m[t.n] = sum
lockUnlock()
}
func main() {
for i := 0;i<100;i++ {
t := &task{n:i}
go calc(t)
}
time.Sleep(10 * time.Second)
lock.Lock()
for k,v := range m {
fmt.Printf("%d!=%v\n",k,v)
}
lock.Unlock()
}
介绍:本质上是一个队列/容器,先进先出,类似unix中的管道pipe
定义:需要指定勇气中元素的类型 var 变量名 chan 数据类型
var test chan int var test chan string var test chan map[string]string var test chan stcurt var test chan *stcurt //定义一个地址,只能传入地址
入队:a <- 100
出队:data := <-a
//test1
func main() {
var c chan int
fmt.Printf("c =%v\n",c)
c = make(chan int,10) //如果不分配空间,则入队一直阻塞,运行报错
fmt.Printf("c = %v\n",c)
c <- 100 //<-c不给变量存储则为丢弃这个元素
data := <-c
fmt.Println("data",data)
}
//test2
type student struct {
name string
}
func main() {
var stuChan chan student
stuChan = make(chan *Student,10)
stu := student{name:"stu01"}
stuChan <- stu
}
//test3
func produce(c chan int) {
c <- 1000
fmt.Println("produce finished")
}
func consume (c chan int) {
data := <-c
fmt.Println("data",data)
}
func main() {
var c chan int
fmt.Printf("c = %v\n",c)
c = make(chan int)
go produce(c)
go consume(c)
time.Sleep(time.Second * 3)
} //不带缓冲区的队列,有出队的时候才能入队,否则入队失败
//chan和goroutine同步
func hello(c chan bool){
fmt.Println("hello goroutine")
c <- true
}
func main(){
var exitChan chan bool
exitChan = make(chan bool)
go hello(exitChan)
fmt.Println("main thread terminate")
<-exitChan
}
//单向chan
func sendData(sendch chan<- int) { chan<- 表示之能入队
sendch <- 10
}
func readData(sendch <-chan int) { <- chan 表示只能出队
data := <-sendch
fmt.Println("data:", data)
}
func main() {
chnl := make(chan int)
go sendData(chnl)
readData(chnl)
}
//chan关闭
func producer(chnl chan int) {
for i := 0; i < 10; i++ {
chnl <- i
}
close(chnl) //关闭chan
}
func main() {
ch := make(chan int)
go producer(ch)
for {
v, ok := <-ch
if ok == false { //判断chan是否关闭,如果无法判断管道是否关闭会一直取出默认值0保持死循环
fmt.Println("chan is closed")
break
}
fmt.Println("Received", v, ok)
}
}
//for range
func produer(chnl chan int) {
for i := 0; i < 10; i++ {
chnl <- i
}
close(chnl)
}
func main() {
ch := make(chan int)
go produer(ch)
for v := range ch { //chan关闭无数据后自动运行结束
fmt.Println("receive:", v)
}
}
//带缓冲区的chanel
func write( ch chan int) {
for i:= 0;i<5;i++ {
ch <- i
fmt.Println("successfully wrote",i,"to ch")
}
close(ch)
}
func main() {
ch := make(chan int,2)
go write(ch)
time.Sleep(2 * time.Second)
for v := range ch {
fmt.Println("read value",v,"from ch")
time.Sleep(2 *time.Second)
}
}
//channel的长度和容量
func main() {
ch := make(chan string,3)
ch <- "naveen"
ch <- "paul"
fmt.Println("capacity is",cap(ch))
fmt.Println("length is",len(ch))
fmt.Println("read value",<-ch)
fmt.Println("new length is",len(ch))
}
//waitgroup等待一组goroutine结束,使用不带缓冲区的channel实现
func process(i int,ch chan bool) {
fmt.Println("started Goroutine",i)
time.Sleep(2 * time.Second)
fmt.Printf("Goroutine %d ended\n",i)
ch <- true
}
func main() {
no := 3
exitChan := make(chan bool,no)
for i := 0;i<no;i++ {
go process(i,exitChan)
}
for i:= 0;i<no;i++ {
<exitChan
}
fmt.Println("All goroutines finshed executing")
}
//使用sync-WaitGroup实现
func process(i int,wg *sync.WaitGroup) {
fmt.Println("started Goroutine",i)
time.Sleep(2 * time.Second)
fmt.Printf("Goroutine %d ended\n",i)
wg.Done() //wg-1
}
func main() {
no := 3
var wq sync.WaitGroup //定义一个wgh,默认为0
for i := 0; i<no; i++ {
wg.Add(1) wg+1
go process(i,&wg)
}
wg.Wait() //当wg为0时才会向下执行
fmt.Println("All goroutines finished executing“)
}”
定义:多channel操作,同时监听一个或多个channel,直到其中一个channel ready,如果其中合格多个chgannel同时ready,随机选择一个进行操作,语法和weitch case类似,只获取一个数值就结束
func server1(ch chan string) {
time.Sleep(time.Second * 3)
ch <- "response from server1"
}
func server2(ch chan string) {
time.Sleep(time.Second)
ch <-"response from server2")
}
func main() {
output1 := make(chan string)
output2 := make(chan stirng)
go server1(output1)
go server2(output2)
//s1 := <-output1 //等待3s
//fmt.Println("s1:",s1)
//s2 := <-output2 //等待1s后等待s1结束再执行
//fmt.Println("s2",s2)
select { //最终只取一个channel的结果
case s1 := <-output1:
fmt.Println("s1:",s1)
case s2 := <-output2:
fmt.Prinln("s2:",s2)
}
}
default分支:放case分支的channel都没有ready的话,执行default,用来判断channel是否满了或者为空
//test1
func server1(ch chan string) {
time.Sleep(time.Second * 3)
ch <- "resdponse from server1"
}
func server2(ch chan string) {
time.Sleep(time.Second)
ch <- "response from server2"
}
func main() {
output1 := make(chan string)
output2 := make(chan string)
go server1(output1)
go server2(output2)
select { //最终只取一个channel的结果
case s1 := <- output1:
fmt.Println("s1;",s1)
case s2 := <-output2:
fmt.Println("s2:",s2)
default:
fmt.Println("run default") //因为s1和s2需要等待,default瞬间执行
}
}
//test2
func write(ch chan string) {
for {
select {
case ch <- "hello":
fmt.,Println("write succ")
default:
fmt.Println("channel is full")
}
time.Sleep(time.Millisecond * 500)
}
}
func main() {
output1 := make(chan string,10)
go write(output1)
for s := range.output1 {
fmt.Println("recv:"s)
time.Sleep(time.Second)
}
}
原文:https://www.cnblogs.com/parallel-Y/p/11432988.html