最美的标题

定时器Timer:结构: —— 只能单次定时

    type Timer struct {
C <-chan Time	// 读 C 阻塞,当定时时间到时,系统自动写入当前时间。阻塞解除。
r runtimeTimer
    }
使用方法:
	1. 创建 Timer : time.NewTimer()

	2. 读 Timer 成员 C 。直到系统时间。

延时定时:
1. sleep(时间)

2. newTimer(时间)    <-C

3. <-time.After(时间)		【重点】

定时器停止、重置:

1. t1 := time.NewTimer()

	t1.stop()

2.  t1 := time.NewTimer()

	t1.reset(新时间)

Ticker: —— 周期定时。

type Ticker struct {
	 C <-chan Time 	
	r runtimeTimer
}
特性:一次设定,系统循环写入C 系统时间。

ticker 只有 stop() 没有 reset() 方法

select :监听 channel 上的 数据流动(r、w) 【重点】

语法:
        select {
	case  channnel IO 操作

	case  channnel IO 操作:
	.....
	default :
        }

select 使用注意事项:

1. case分支中必须是一个 IO操作:

2. 当case分支不满足监听条件,阻塞当前 case 分支

3. 如果同时有多个case分支满足,select随机选定一个执行( select底层实现,case对应一个 goroutine)

4. 一次select 监听,只能执行一个case分支。通常将select放于for 循环中

5. default 在所有case均不满足时,默认执行的分组,为防止忙轮询,通常将 for 里 select中的 default 省略。

【重要结论】:使用 select的 go程,与其他go程间 采用  【异步通信】 通信方式。

斐波那契数列:

1,1,2,  3, 5, 8, 13, 21, 34, 55, 89 。。。		—— 15 

select 实现的 超时:【重点】

1. select {
         case ch<-:
         case <-time.After(时间) :
    } 

2.  当 select 监听的 ch 写事件满足时。会重置 time.After 的定时器时间。

3.  只有 select 监听的所有case均不满足,time.After 计时满 ,该 case 才满足监听条件(读事件)。

死锁: 运行时错误 —— 在编码期间提早预见,提早规避。

死锁1: 同一个go程,使用一个channel 自己读自己写。

死锁2: 读写位于两个go程间。但是go程的创建在 r 或 w 之后。r 或 w 会造成go程阻塞,导致另一个go程无法创建。

死锁3: 两个go程,两个channel。 go程1 对channel1读,成功写入 channel2. go程2 对channel2读,成功写入 channel1.

	互相死锁。

死锁4: channel 和 读写锁、互斥锁。

互斥锁(互斥量):

建议锁。不具有强制性。

保护公共区,被锁住后,只有成功加锁的 go 程能正常访问。其他go程阻塞在 锁的等待事件上。

使用注意:
	1. 公共区访问开始之前,加锁

	2. 访问结束后 立即解锁。 锁的 粒度 越小越好。

使用方法:
	1. 定义 互斥锁。 var mutex sync.Mutex

	2. 加锁 mutex.Lock()

		。。。 访问公共区数据

	3. 解锁 mutex.Unlock()

读写锁:

读共享,写独占。
	
写锁优先级高于读锁。

使用注意:
	1. 公共区访问开始之前,加锁

	2. 访问结束后 立即解锁。 锁的 粒度 越小越好。

	3. 锁只有一把。但是具备两种加锁属性。读属性加锁。写属性加锁。
使用方法:

	1. 定义 读写锁。 var rwmutex sync.RWMutex

	2. 加读锁 rwmutex.RLock()			加写锁  	rwmutex.Lock()	

		。。。 读公共区数据				。。。 写公共区数据	

	3. 解锁 rwmutex.RUnlock()			解写锁	rwmutex.UnLock()	

多go程同步时,尽量少 锁(读写锁、互斥锁)、和 channel 【混用】。	—— 条件变量。

条件变量:
Cond 语法:

type Cond struct {
	noCopy noCopy
	
	L Locker		// 锁:互斥、读写

	notify  notifyList
	checker copyChecker
}

Cond.Wait():	
	1)  阻塞等待条件变量满足

	2)释放已经掌握的互斥锁  (1/2 两步为 原子操作。)

		。。。 阻塞等。

	3) 被唤醒时,解除阻塞,重新加锁

Cond.Signal():

	唤醒阻塞在条件变量上的 一个 对象。

Cond.Broadcast()

	唤醒阻塞在条件变量上的 所有 对象。

条件变量使用流程: — 生产者为例

1. 创建条件变量	var cond Sync.Cond	—— 结构体

2. 初始化 条件变量使用的 锁 	cond.L = new(sysc.Mutex)

3. 给条件变量的 互斥锁 加锁	cond.L.Lock()

4. 判断条件变量是否满足。 调用wait :1) 2) 3)  	

	for len(ch) == cap(ch) {   		// 此处判断,必须使用 for ,而不能使用 if
		cond.Wait()
	}

5. 生产数据:	产生随机数 num := rand.Intn()

6. 写入公共区(缓冲区)	ch <- num

7. 唤醒对端(消费者)	cond.Signal()

8. 给条件变量的 互斥锁 解锁	cond.L.UnLock()

你可能感兴趣的:(最美的标题)