Go语言管道与高并发实战

固定时长定时器

  1. 写法一
package main

import (
	"fmt"
	"time"
)

func main() {
	//创建3秒定时器
	timer := time.NewTimer(3*time.Second)
	fmt.Println("定时器创建完毕")

	//打印当前时间
	fmt.Println(time.Now())
	x := <-timer.C
	fmt.Println(x)
}

2) 写法二

package main

import (
	"fmt"
	"time"
)

func main() {
	//打印当前时间
	fmt.Println(time.Now())

	x := <-time.After(3*time.Second)
	fmt.Println("定时器创建完毕")
}	

周期性长定时器

package main

import (
	"fmt"
	"time"
)

func main() {
	//创建一个1秒为周期的秒表
	ticker := time.NewTicker(1 * time.Second)

	var i int
	for {
		//每隔1秒读出当前时间
		x := <-ticker.C
		fmt.Print("\n", x)

		//10秒后停止计时并退出
		i++
		if i > 9 {
			ticker.Stop()
			break
		}
	}
	fmt.Println("计时结束")
}

定时器的终止和重置

package main

import (
	"time"
	"fmt"
)

func main() {

	timer := time.NewTimer(3 * time.Second)
	fmt.Println(time.Now(), "炸弹将于3秒后引爆")

	//趁定时器未到时间,将定时器终止
	timer.Stop()
	fmt.Println("炸弹已被拆除,定时器失效")

	//定时器已被叫停,其时间管道永远读不出数据了--死锁
	//fatal error: all goroutines are asleep - deadlock!
	t := <-timer.C
	fmt.Println("炸弹引爆于", t)
}

等待组

package main

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

func main041() {

	//创建任务等待组
	var wg sync.WaitGroup

	//向等待组中添加任务
	wg.Add(1)
	wg.Add(1)
	wg.Add(1)

	//从等待组中抹掉任务
	wg.Done()
	wg.Done()
	wg.Done()

	//阻塞等待至等待组中的任务数为0
	wg.Wait()

}

func main() {
	var wg sync.WaitGroup

	wg.Add(1)
	go func() {
		for i := 0; i < 5; i++ {
			fmt.Println("子协程1", i)
			<-time.After(1 * time.Second)
		}
		fmt.Println("子协程1结束任务")
		wg.Done()
	}()

	wg.Add(1)
	go func() {
		var i int
		ticker := time.NewTicker(1 * time.Second)
		for {
			<-ticker.C
			i++
			fmt.Println("子协程2", "秒表:", i)
			if i > 9 {
				break
			}
		}
		fmt.Println("子协程2结束任务")
		wg.Done()
	}()

	//等待组阻塞等待至记录清零为止
	wg.Wait()
	fmt.Println("END")
}

互斥锁
1)并发安全问题,每次累加数据都不一样

package main

import (
	"fmt"
	"sync"
)

func main() {
	//创建任务等待组
	var wg sync.WaitGroup
	var money = 2000

	for i := 0; i < 10; i++ {
		wg.Add(1)
		go func() {
			//并发安全问题,每次累加数据都不一样
			for j := 0; j < 10000; j++ {
				money += 1
			}
			wg.Done()
		}()
	}

	//阻塞等待至等待组中的任务数为0
	wg.Wait()
	fmt.Println("最终金额", money)
}

2)加互斥锁

package main

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

var wg sync.WaitGroup

func main() {
	var money = 2000

	//一支麦克
	var mt sync.Mutex

	wg.Add(1)
	go func() {
		fmt.Println("鹤姐开始抢麦")

		//谁抢到麦谁才有资格修改money,其他抢麦的协程就必须阻塞等待
		mt.Lock()
		fmt.Println("鹤姐抢到了麦,何洁开始嗨")

		money -= 300
		<-time.After(10*time.Second)

		//曲罢弃麦,其它人再去哄抢
		mt.Unlock()
		fmt.Println("鹤姐弃麦")

		wg.Done()
	}()

	wg.Add(1)
	go func() {
		fmt.Println("鹤哥开始抢麦")

		//谁抢到麦谁才有资格修改money,其他抢麦的协程就必须阻塞等待
		mt.Lock()
		fmt.Println("鹤哥抢到了麦,鹤哥开始嗨")
		money -= 500
		<-time.After(10*time.Second)
		//曲罢弃麦,其它人再去哄抢
		mt.Unlock()
		fmt.Println("鹤哥弃麦")

		wg.Done()
	}()

	/*不抢麦的人不会被阻塞*/

	wg.Add(1)
	go func() {
		fmt.Println("abcdefg")
		<-time.After(1*time.Second)
		fmt.Println("hijklmn")
		<-time.After(1*time.Second)
		fmt.Println("opqrst")
		<-time.After(1*time.Second)
		fmt.Println("uvwxyz")
		wg.Done()
	}()

	wg.Wait()
}

信号量控制最大并发数
控制最大并发数量

package main

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

var wg08 sync.WaitGroup
var chSem chan int

func main() {

	//semaphore信号量
	chSem = make(chan int, 5)

	for i := 0; i < 100; i++ {
		wg08.Add(1)
		go getSqrt(i)
	}

	wg08.Wait()
}

func getSqrt(n int) {
	//规定:所有并发任务都必须注册在信号量管道里
	chSem <- n

	fmt.Printf("%d的平方根是%.2f\n", n, math.Sqrt(float64(n)))
	<- time.After(10 * time.Second)

	//任务结束后从信号量管道注销,给其它腾出空间
	<-chSem
	wg08.Done()
}

死锁现象
1)自己阻塞自己

package main

import "fmt"

//自己阻塞自己
func main() {
	ch := make(chan int, 0)

	ch <- 123
	x := <-ch
	fmt.Println(x)
}

2)开塞露协程-开晚了

package main

import "fmt"
//开塞露协程-开晚了
func main() {
	ch := make(chan int, 0)

	ch <- 123
	go func() {
		x := <-ch
		fmt.Println(x)
	}()
}

3)管道读写时,相互要求对方先读/写,自己在写/读,造成死锁

package main

import (
	"fmt"
)

/*读写锁定相互阻塞,形成隐形死锁*/
func main() {

	chHusband := make(chan int, 0)
	chWife := make(chan int, 0)

	//老公
	go func() {
		for{
			select {
			//只要我有钱我就给你发红包
			case <- chHusband:
				chWife <- 123
				fmt.Println("老公:我已经给你发123元红包了")
			case chWife <- 1:
				fmt.Println("老公:我已经给你发1元红包了")
			}
		}

	}()

	//老婆
	select {
	//只要我有钱我就给你发红包
	case <- chWife:
		chHusband <- 123
		fmt.Println("老婆:我已经给你发123元红包了")
	}

	fmt.Println("THE END")

}

4)读写锁定相互阻塞,形成隐形死锁

package main

import (
	"fmt"
	"runtime"
	"sync"
)

/*读写锁定相互阻塞,形成隐形死锁*/
func main() {

	var rwm09 sync.RWMutex
	ch := make(chan int, 0)
	//子协程负责写入
	go func() {
		//连锁都抢不到555...
		rwm09.Lock()
		ch <- 123
		rwm09.Unlock()
	}()

	go func() {
		//本协程负责读出
		rwm09.RLock()
		//只要读不到内容就永远阻塞
		x := <-ch
		fmt.Println("读到", x)
		rwm09.RUnlock()
	}()

	for {
		//通知垃圾回收器来清理垃圾(即使不叫也会定时清理)
		runtime.GC()
	}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值