go基础笔记----Goroutine and Channel

  • goroutine
package main

import (
	"fmt"
	"time"
)

/*
	goroutine 类协程{
		定义{
			任何函数只需加上go就能送给调度器运行
			不需要在定义时区分是否时异步函数
			调度器在合适的点进行切换
			使用 -race来检测数据访问冲突
		}

		goroutine可能的切换点{
			1.I/O,select
			2.channel
			3.等待锁
			4.函数调用(有时)
			5.runtime.Gosched()   //在某个点愿意交出控制权
			6.以上只是参考,不能保证切换,不能保证在其他地方不切换
		}

		内部结构{
			调度器
			线程{
				goroutine*n
			}
		}
	}

	coroutine(协程){
		轻量级"线程"{
			非抢占式多任务处理,由协程主动交出控制权
			编译器/解释器/虚拟机层面的多任务
			多个协程可能在一个或多个线程上运行
		}
		子程序是协程的一个特例{
			普通函数{
				线程{
					main->doWork
				}
			}
			协程{
				线程(可能是多个线程,底层实现不用管){
					main<->doWork 有一个通道,数据可以双向流通,控制权也可双向流通
				}
			}
		}
	}
*/

func main() {
	// var a [10]int
	for i := 0; i < 1000; i++ {
		go func(i int) { // go run -race test.go  检测数据访问冲突 rece condition
			for {
				fmt.Printf("Hello from"+"goroutine %d \n", i)
				// a[i]++
				// runtime.Gosched() // 很少用到
			}
		}(i)
	}

	time.Sleep(time.Minute)
	// fmt.Println(a)
}
  • channel.go
package main

import (
	"fmt"
	"time"
)

/*
	channel{
		包含{
			goroutine <= channel => goroutine * n
			调度器
		}
		理论基础{
			communication Sequential Process(CSP模型)
			不要通过共享内存来通信,通过通信来共享内存
		}
	}
*/

func worker(id int, c chan int) {
	for n := range c { // 接收完毕 关闭1
		// n, ok := <-c // 接收完毕 关闭2
		// if !ok {
		// 	break
		// }
		fmt.Printf("Worker %d received %d \n", id, n)
	}
}

func createWorker(id int) chan<- int {
	c := make(chan int)

	go worker(id, c)
	return c
}

func chanDemo() {
	// var c chan int // 只是定义 没有开辟内存空间 c == nil
	var channels [10]chan<- int
	for i := 0; i < 10; i++ {
		channels[i] = createWorker(i) // 开辟内存空间
	}

	for i := 0; i < 10; i++ {
		channels[i] <- 'a' + i
	}

	for i := 0; i < 10; i++ {
		channels[i] <- 'A' + i
	}

	time.Sleep(time.Millisecond)
}

func bufferedChannel() {
	c := make(chan int, 3) // 新建一个大小为3的缓冲区
	go worker(0, c)
	c <- 'a'
	c <- 'b'
	c <- 'c'
	time.Sleep(time.Millisecond) //
}

func channelClose() {
	// 永远是发送方来close
	c := make(chan int, 3) // 新建一个大小为3的缓冲区
	go worker(0, c)
	c <- 'a'
	c <- 'b'
	c <- 'c'
	close(c)
	// time.Sleep(time.Millisecond)
}

func main() {
	fmt.Println("Channel as first-class citizen")
	chanDemo()
	fmt.Println("Buffered channel")
	bufferedChannel()
	fmt.Println("Channel close and range")
	channelClose()
}
  • done.go
package main

import (
	"fmt"
	"sync"
)

/*
	使用WaitGroup
*/

func doWorker(id int, w worker) {
	for n := range w.in { // 接收完毕 关闭1
		fmt.Printf("Worker %d received %c \n", id, n)
		w.done()
	}
}

type worker struct {
	in chan int
	// done chan bool
	// wg *sync.WaitGroup
	done func()
}

func createWorker(id int, wg *sync.WaitGroup) worker {
	w := worker{
		in:   make(chan int),
		done: func() { wg.Done() },
	}

	go doWorker(id, w)
	return w
}

func chanDemo() {
	var wg sync.WaitGroup

	var workers [10]worker
	for i := 0; i < 10; i++ {
		workers[i] = createWorker(i, &wg)
	}

	// wg.Add(20)

	for i, worker := range workers {
		worker.in <- 'a' + i
		wg.Add(1)
	}

	for i, worker := range workers {
		worker.in <- 'A' + i
		wg.Add(1)
	}

	wg.Wait()
	// wait for all of them
	// for _, worker := range workers {
	// 	<-worker.done
	// }
}

func main() {
	chanDemo()
}
  • select.go
package main

import (
	"fmt"
	"math/rand"
	"time"
)

func generator() chan int {
	out := make(chan int)
	go func() {
		i := 0
		for {
			time.Sleep(time.Duration(rand.Intn(1500)) * time.Millisecond)
			out <- i
			i++
		}
	}()
	return out
}

func worker(id int, c chan int) {
	for n := range c { // 接收完毕
		time.Sleep(time.Second)
		fmt.Printf("Worker %d received %d \n", id, n)
	}
}

func createWorker(id int) chan<- int {
	c := make(chan int)

	go worker(id, c)
	return c
}

func main() {
	var c1, c2 = generator(), generator() // c1 and c2 == nil
	var worker = createWorker(0)

	var values []int

	// 从启动程序过去的时间
	tm := time.After(10 * time.Second)

	// 每过多长时间
	tick := time.Tick(time.Second)

	for {

		// nil channel 有值的时候才会初始化
		var activeWorker chan<- int
		var activeValue int
		if len(values) > 0 {
			activeWorker = worker
			activeValue = values[0]
		}

		select {
		case n := <-c1:
			values = append(values, n)
		case n := <-c2:
			values = append(values, n)
		case activeWorker <- activeValue:
			values = values[1:]
		// case n := <-c1:
		// fmt.Println("Received from c1:", n)
		// case n := <-c2:
		// fmt.Println("Received from c2:", n)

		// 非阻塞式从chan获取值
		// default:
		// fmt.Println("No value received")

		// 每次执行select 的时间 相邻两个请求时间的time out
		case <-time.After(800 * time.Millisecond):
			fmt.Println("time out")

		// 反应系统的状态
		case <-tick:
			fmt.Println("queue len = ", len(values))

		// 总的时间来确定程序时常
		case <-tm:
			fmt.Println("bye")
			return
		}
	}

}
  • atomic
package main

import (
	"fmt"
	"sync"
	"time"
)

type atomicInt struct {
	value int
	lock  sync.Mutex
}

func (a *atomicInt) increment() {
	a.lock.Lock()
	defer a.lock.Unlock()
	a.value++
}

func (a *atomicInt) get() int {
	a.lock.Lock()
	defer a.lock.Unlock()
	return a.value
}

func main() {
	var a atomicInt
	a.increment()
	go func() {
		a.increment()
	}()
	time.Sleep(time.Millisecond)
	fmt.Println(a.get())
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值