(3).强制取消定时器
package main import ( "fmt" "time" ) func main() { 1.第一种定义定时器 //timer := time.NewTimer(time.Second * 2) //设置指定时间后执行管道读出 //fmt.Printf("现在的时间是: %v\n", time.Now()) //t1 := <-timer.C //阻塞的,指定时间到了便会读出 //fmt.Printf("管道读出的时间是: %v\n", t1) //fmt.Printf("现在的时间是: %v\n", time.Now()) //timer := time.NewTimer(time.Second * 2) //设置指定时间后执行管道读出 //<-timer.C //fmt.Printf("现在的时间是: %v\n", time.Now()) fmt.Printf("现在的时间是: %v\n", time.Now()) timer := time.NewTimer(time.Second * 2) go func() { <-timer.C println("func.....") }() s := timer.Stop() // 我们执行这个方法那么定时器就不会执行 if s { println("stop....") } fmt.Printf("现在的时间是: %v\n", time.Now()) time.Sleep(time.Second * 3) }
(4).定时器时间的修改
package main import ( "fmt" "time" ) func main() { 1.第一种定义定时器 //timer := time.NewTimer(time.Second * 2) //设置指定时间后执行管道读出 //fmt.Printf("现在的时间是: %v\n", time.Now()) //t1 := <-timer.C //阻塞的,指定时间到了便会读出 //fmt.Printf("管道读出的时间是: %v\n", t1) fmt.Printf("现在的时间是: %v\n", time.Now()) timer := time.NewTimer(time.Second * 2) //设置指定时间后执行管道读出 timer.Reset(time.Second * 5) <-timer.C fmt.Printf("现在的时间是: %v\n", time.Now()) //fmt.Printf("现在的时间是: %v\n", time.Now()) //timer := time.NewTimer(time.Second * 2) //go func() { // <-timer.C // println("func.....") //}() //s := timer.Stop() // 我们执行这个方法那么定时器就不会执行 //if s { // println("stop....") //} //fmt.Printf("现在的时间是: %v\n", time.Now()) //time.Sleep(time.Second * 3) }
9.并发编程之Ticker
Timer只执行一次,Ticker可以周期的执行
(1).定义方式
1.第一种定义方式 time.NewTicker()
(2).Ticker实列
- 基础使用
每隔两秒打印一下
package main import "time" func main() { ticker := time.NewTicker(time.Second * 2) //每两秒执行一次 counter := 1 for _ = range ticker.C { //如果没有变量接受那么可以省略 : ------>出现周期性的使用这个定时器 println("ticker....") counter++ if counter >= 5 { ticker.Stop() break } } }
package main import ( "fmt" "time" ) func main() { ticker := time.NewTicker(time.Second) //每两秒执行一次 chanInt := make(chan int) go func() { for _ = range ticker.C { //如果没有变量接受那么可以省略 : ------>出现周期性的使用这个定时器 select { case chanInt <- 1: println("send: 1") case chanInt <- 2: println("send: 2") case chanInt <- 1: println("send: 3") } } }() sum := 0 for v := range chanInt { fmt.Printf("receice: %v\n", v) sum += v if sum >= 10 { break } } }
10.并发编程之原子变量的引入
(1).我们可以通过枷锁实现同步
为什么我实现枷锁: 联想银行的同步取钱操作。
package main import ( "fmt" "sync" "time" ) /* 银行业务. 一定要考虑好保护加锁 */ var mt sync.Mutex //定义锁 var i = 100 func add() { mt.Lock() //当我上锁了,别人对我下面用的变量都不能用, i++ mt.Unlock() } func sub() { mt.Lock() i-- mt.Unlock() } func main() { for i := 0; i < 100; i++ { go add() go sub() } time.Sleep(time.Second * 1) fmt.Printf("%v", i) // 假如不上锁的话,会出现数据合演不对。 }
(2).autoic包实现乐观锁
package main import ( "fmt" "sync/atomic" "time" ) /* 银行业务. 一定要考虑好保护加锁 */ var i int32 = 100 func add() { // 这里的机制类似于 乐观锁的操作: 在我修改之前不允许有人修改,否则就不修改 atomic.AddInt32(&i, 1) // 就是值int32这个类型的那个地址,每次调用添加几 } func sub() { atomic.AddInt32(&i, -1) } func main() { for i := 0; i < 100; i++ { go add() go sub() } time.Sleep(time.Second * 1) fmt.Printf("%v", i) // 假如不上锁的话,会出现数据合演不对。 }
11.并发编程之原子操作详解
(1).automic的介绍
automic
提供的原子操作能够确保任意时刻只有一个协程对变量进行操作,善用 atomic
能够避免程序中出现大量的锁的操作。
automic常见操作有:
- 增减
- 载入 (读)
- 比较并交换 cas
- 交换
- 存储 (写)
(2).原子性增减操作
automic包中提供了如下以Add为前缀的增减 操作:
func AddInt32(add *int32,delta int32) (new int32) func AddInt32(add *int64,delta int64) (new int64) func AddUInt32(add *uint32,delta uint32) (new uint32) func AddInt32(add *uint64,delta uint64) (new uint64) func AddInt32(add *uintptr,delta uintptr) (new uintptr) //指针类型
增减的操作:
func add() { // 这里的机制类似于 乐观锁的操作: 在我修改之前不允许有人修改,否则就不修改 atomic.AddInt32(&i, 1) // 就是值int32这个类型的那个地址,每次调用添加几 } func sub() { atomic.AddInt32(&i, -1) }
(3).原子性载入和存储
相当于银行的存钱和查看余额。
package main import ( "fmt" "sync/atomic" "time" ) /* 银行业务. 一定要考虑好保护加锁 */ var i int32 = 100 func add() { // 这里的机制类似于 乐观锁的操作: 在我修改之前不允许有人修改,否则就不修改 atomic.AddInt32(&i, 1) // 就是值int32这个类型的那个地址,每次调用添加几 atomic.StoreInt32(&i, 200) //存储: 相当于写的操作 当我写的时候不允许其他人写, -》类似于向银行存钱 val := atomic.LoadInt32(&i) //载入 也就是读的操作 当我读取的时候不允许其他人读 fmt.Printf("add-> %v\n", val) } func sub() { atomic.AddInt32(&i, -1) atomic.StoreInt32(&i, 200) //存储: 相当于写的操作 当我写的时候不允许其他人写, val := atomic.LoadInt32(&i) //载入 也就是读的操作: 当我读取的时候不允许其他人读 fmt.Printf("sub-> %v\n", val) } func main() { for i := 0; i < 100; i++ { go add() go sub() } time.Sleep(time.Second * 1) fmt.Printf("%v", i) // 假如不上锁的话,会出现数据合演不对。 }
(4).原子性比较交换
假如说: 旧值一直没有发生变化,那么就和新值发生交换返回true,否则不交换返回false。
package main import ( "fmt" "sync/atomic" "time" ) /* 银行业务. 一定要考虑好保护加锁 */ var i int32 = 100 func add() { // 这里的机制类似于 乐观锁的操作: 在我修改之前不允许有人修改,否则就不修改 atomic.AddInt32(&i, 1) // 就是值int32这个类型的那个地址,每次调用添加几 atomic.StoreInt32(&i, 200) //存储: 相当于写的操作 当我写的时候不允许其他人写, -》类似于向银行存钱 val := atomic.LoadInt32(&i) //载入 也就是读的操作 当我读取的时候不允许其他人读 fmt.Printf("add-> %v\n", val) } func sub() { atomic.AddInt32(&i, -1) atomic.StoreInt32(&i, 200) //存储: 相当于写的操作 当我写的时候不允许其他人写, val := atomic.LoadInt32(&i) //载入 也就是读的操作: 当我读取的时候不允许其他人读 fmt.Printf("sub-> %v\n", val) } func main() { for i := 0; i < 100; i++ { go add() go sub() } time.Sleep(time.Second * 1) swapInt32 := atomic.CompareAndSwapInt32(&i, 100, 200) // 就是说假如值为100那么我们就交换,假如100被修改成其他的值,那么我们就不进行交换返回false -->也就是说有其他线程干扰了就返回flase fmt.Printf("%v", swapInt32) fmt.Printf("%v", i) // 假如不上锁的话,会出现数据合演不对。 }