Go语言进阶第05天(死锁与控制锁)

1.select超时处理

package main

import (
	"fmt"
	"time"
)

func test(ch chan int, quit chan bool)  {
    
    

}

func main00()  {
    
    
	ch := make(chan int)
	quit := make(chan bool)
	go func() {
    
    			// 子go 程获取数据
		for {
    
    
			select {
    
    
			case num := <-ch:
				fmt.Println("num = ", num)
			case <-time.After(3 * time.Second):
				quit <- true
				goto lable
				// return
				// runtime.Goexit()
			}
		}
	lable:
	}()
	for i:=0; i<2; i++ {
    
    
		ch <- i
		time.Sleep(time.Second * 2)
	}
	<-quit 			// 主go程,阻塞等待 子go程通知,退出
	fmt.Println("finish!!!")
}


2.死锁

package main

import "fmt"

// 死锁1
func main0000() {
    
    
	ch := make(chan int) //这就是在main程里面发生的死锁情况
	ch <- 789            //  这里会发生一直阻塞的情况,执行不到下面一句,主进程管道塞入数据的同时没有读出,造成堵塞
	num := <-ch
	fmt.Println("num = ", num)

}

// 死锁2
func main0201() {
    
    
	ch := make(chan int)
	num := <-ch //主进程请求读出同时通道没有数据造成堵塞
	go func() {
    
    
		ch <- 789
	}()

	fmt.Println("num = ", num)
}

// 死锁 3
func main01() {
    
    
	ch1 := make(chan int)
	ch2 := make(chan int)
	go func() {
    
     // 子
		for {
    
    
			select {
    
    
			case num := <-ch1:
				ch2 <- num
			}
		}
	}()
	for {
    
    
		select {
    
    
		case num := <-ch2:
			ch1 <- num
		}
	}
}

3.互斥锁

package main

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

// 使用channel 完成同步
/*var ch = make(chan int)

func printer(str string)  {
	for _, ch := range str {
		fmt.Printf("%c", ch)
		time.Sleep(time.Millisecond * 300)
	}
}

func person1()  {				// 先
	printer("hello")
	ch <- 98
}

func person2()  {				// 后
	<- ch
	printer("world")
}

func main()  {
	go person1()
	go person2()
	for {
		;
	}
}
*/

// 使用 “锁” 完成同步 —— 互斥锁
var mutex sync.Mutex // 创建一个互斥量, 新建的互斥锁状态为 0. 未加锁。 锁只有一把。

func printer(str string) {
    
    
	mutex.Lock() // 访问共享数据之前,加锁
	for _, ch := range str {
    
    
		fmt.Printf("%c", ch)
		time.Sleep(time.Millisecond * 300)
	}
	mutex.Unlock() // 共享数据访问结束,解锁
}

func person1() {
    
     // 先
	printer("hello")
}

func person2() {
    
     // 后
	printer("world")
}

func main02() {
    
    
	go person1()
	go person2()
	for {
    
    

	}
}

4.读写锁死锁

package main

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

var rwMutex1 sync.RWMutex // 锁只有一把, 2 个属性 r w

func readGo(in <-chan int, idx int) {
    
    
	for {
    
    
		rwMutex1.RLock() // 以读模式加锁

		num := <-in
		fmt.Printf("----%dth 读 go程,读出:%d\n", idx, num)
		rwMutex1.RUnlock() // 以读模式解锁
	}
}

func writeGo(out chan<- int, idx int) {
    
    
	for {
    
    
		// 生成随机数
		num := rand.Intn(1000)
		rwMutex1.Lock() // 以写模式加锁
		fmt.Println(num)
		out <- num
		fmt.Printf("%dth 写go程,写入:%d\n", idx, num)
		time.Sleep(time.Millisecond * 300) // 放大实验现象
		rwMutex1.Unlock()
	}
}

func main04() {
    
    
	// 播种随机数种子
	rand.Seed(time.Now().UnixNano())

	// quit := make(chan bool)			// 用于 关闭主go程的channel
	ch := make(chan int) // 用于 数据传递的 channel
	for i := 0; i < 5; i++ {
    
    
		go readGo(ch, i+1)
	}
	for i := 0; i < 5; i++ {
    
    
		go writeGo(ch, i+1)
	}
	for {
    
    
		fmt.Println("aaa")

	}
}

5.读写锁-relock

package main

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

var rwMutex sync.RWMutex // 锁只有一把, 2 个属性 r w

var value int // 定义全局变量,模拟共享数据

func readGo05(idx int) {
    
    
	for {
    
    
		rwMutex.RLock() // 以读模式加锁
		num := value
		fmt.Printf("----%dth 读 go程,读出:%d\n", idx, num)
		rwMutex.RUnlock() // 以读模式解锁
		time.Sleep(time.Second)
	}
}
func writeGo05(idx int) {
    
    
	for {
    
    
		// 生成随机数
		num := rand.Intn(1000)
		rwMutex.Lock() // 以写模式加锁
		value = num
		fmt.Printf("%dth 写go程,写入:%d\n", idx, num)
		time.Sleep(time.Second * 5) // 放大实验现象
		rwMutex.Unlock()
	}
}
func main05() {
    
    
	// 播种随机数种子
	rand.Seed(time.Now().UnixNano())

	for i := 0; i < 5; i++ {
    
     // 5 个 读 go 程
		go readGo05(i + 1)
	}

	for i := 0; i < 5; i++ {
    
     //
		go writeGo05(i + 1)
	}
	for {
    
    

	}
}

6.读写锁-channel

**package main

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

// var value06 int		// 定义全局变量,模拟共享数据
func readGo06(in <-chan int, idx int) {
    
    
	for {
    
    
		num := <-in // 从 channel 中读取数据
		fmt.Printf("----%dth 读 go程,读出:%d\n", idx, num)
		time.Sleep(time.Second)
	}
}
func writeGo06(out chan<- int, idx int) {
    
    
	for {
    
    
		// 生成随机数
		num := rand.Intn(1000)
		out <- num // 写入channel
		fmt.Printf("%dth 写go程,写入:%d\n", idx, num)
		time.Sleep(time.Millisecond * 300) // 放大实验现象
	}
}
func main06() {
    
    
	// 播种随机数种子
	rand.Seed(time.Now().UnixNano())
	ch := make(chan int)

	for i := 0; i < 5; i++ {
    
     // 5 个 读 go 程
		go readGo06(ch, i+1)
	}
	for i := 0; i < 5; i++ {
    
     //
		go writeGo06(ch, i+1)
	}
	for {
    
    

	}
}
**

7.生产者消费者模型

package main

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

func producer(out chan<- int, idx int) {
    
    
	for i := 0; i < 50; i++ {
    
    
		num := rand.Intn(800)
		fmt.Printf("生产者%dth,生产:%d\n", idx, num)
		out <- num
	}
	close(out)
}

func consumer(in <-chan int, idx int) {
    
    
	for num := range in {
    
    
		fmt.Printf("-----消费者%dth,消费:%d\n", idx, num)
	}
}

func main07() {
    
    
	product := make(chan int)
	rand.Seed(time.Now().UnixNano())

	for i := 0; i < 5; i++ {
    
    
		go producer(product, i+1) // 1 生产者
	}
	for i := 0; i < 5; i++ {
    
    
		go consumer(product, i+1) // 3 个消费者
	}
	for {
    
    

	}
}

8.生产者消费者条件控制

package main

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

var cond sync.Cond // 定义全局条件变量

func producer08(out chan<- int, idx int) {
    
    
	for {
    
    
		// 先加锁
		cond.L.Lock()
		// 判断缓冲区是否满
		for len(out) == 5 {
    
    
			cond.Wait() // 1. 2. 3.
		}
		num := rand.Intn(800)
		out <- num
		fmt.Printf("生产者%dth,生产:%d\n", idx, num)
		// 访问公共区结束,并且打印结束,解锁
		cond.L.Unlock()
		// 唤醒阻塞在条件变量上的 消费者
		cond.Signal()
		time.Sleep(time.Millisecond * 200)
	}
}

func consumer08(in <-chan int, idx int) {
    
    
	for {
    
    
		// 先加锁
		cond.L.Lock()
		// 判断 缓冲区是否为空
		for len(in) == 0 {
    
    
			cond.Wait()
		}
		num := <-in
		fmt.Printf("-----消费者%dth,消费:%d\n", idx, num)
		// 访问公共区结束后,解锁
		cond.L.Unlock()
		// 唤醒 阻塞在条件变量上的 生产者
		cond.Signal()
		time.Sleep(time.Millisecond * 200)
	}
}

func main() {
    
    
	product := make(chan int, 5)
	rand.Seed(time.Now().UnixNano())

	quit := make(chan bool)

	// 指定条件变量 使用的锁
	cond.L = new(sync.Mutex) // 互斥锁 初值 0 , 未加锁状态

	for i := 0; i < 5; i++ {
    
    
		go producer08(product, i+1) // 1 生产者
	}
	for i := 0; i < 5; i++ {
    
    
		go consumer08(product, i+1) // 3 个消费者
	}
	/*	for {
		runtime.GC()
	}*/
	<-quit

}

猜你喜欢

转载自blog.csdn.net/qq_51685718/article/details/127718955