栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Go语言

Go并发编程——channel( 下 )

Go语言 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Go并发编程——channel( 下 )

time包中的定向通道 (⼀)、Timer结构体
  1. 计时器类型表示单个事件。当计时器过期时,当前时间将被发送到C上(C是⼀
    个只读通道<-chan time.Time,该通道中放⼊的是Time结构体),除⾮计时器是
    AfterFunc创建的。计时器必须使⽤NewTimer或AfterFunc创建。
  2. Timer结构体的源码
// The Timer type represents a single event.
// When the Timer expires, the current time will be sent on C,
// unless the Timer was created by AfterFunc.
// A Timer must be created with NewTimer or AfterFunc.
type Timer struct {
 C <-chan Time
 r runtimeTimer
}
(⼆)、NewTimer函数
  1. NewTimer创建⼀个新的计时器,它会在⾄少持续时间d之后将当前时间发送
    到其通道上。
  2. NewTimer()函数的源码
    // NewTimer creates a new Timer that will send
    // the current time on its channel after at least duration d.
    func NewTimer(d Duration) *Timer
  3. 示例代码
//.创建计时器
timer1 := time.NewTimer(5 * time.Second)
fmt.Printf("%Tn", timer1) /
 var wg sync.WaitGroup
 wg.Add(4)
 go saleTickets("售票⼝1", &wg) //g1
 go saleTickets("售票⼝2", &wg) //g2
 go saleTickets("售票⼝3", &wg) //g3
 go saleTickets("售票⼝4", &wg) //g4
 wg.Wait()
 fmt.Println("所有⻋票已售空。程序结束!") }
func saleTickets(name string, wg *sync.WaitGroup) {
 for {
 mutex.Lock()
 if tickts > 0 {
 time.Sleep(1 * time.Second)
 fmt.Println(name, ":", tickts) //1
 tickts--
 } else {
 fmt.Println(name, ",结束卖票。。")
 mutex.Unlock()
 break
 }
 mutex.Unlock() //解锁
 }
 wg.Done()
}
(⼆)、读写互斥锁RWMutex
  1. 原型
    type RWMutex struct {
    w Mutex // held if there are pending writers
    writerSem uint32 // semaphore for writers to wait for completing readers
    readerSem uint32 // semaphore for readers to wait for completing writers
    readerCount int32 // number of pending readers
    readerWait int32 // number of departing readers
    }
    RWMutex是读写互斥锁。该锁可以被同时多个读取者持有或唯⼀个写⼊者持有。RWMutex可以创建为其他结构体的字段;零值为解锁状态。RWMutex类型的锁也和线程⽆关,可以由不同的线程加读取锁/写⼊和解读取锁/写⼊锁。
    锁定的规则:
    读写锁的使⽤中:写操作都是互斥的、读和写是互斥的、读和读不互斥。
    理解为:
    可以多个goroutine同时读取数据,但是写只允许⼀个goroutine写数据。
  2. Mutex中的⽅法
  • func (rw *RWMutex) Lock()
    Lock⽅法将rw锁定为写⼊状态,禁⽌其他线程读取或者写⼊。
  • func (rw *RWMutex) Unlock()
    Unlock⽅法解除rw的写⼊锁状态,如果m未加写⼊锁会导致运⾏时错误。
  • func (rw *RWMutex) RLock()
    RLock⽅法将rw锁定为读取状态,禁⽌其他线程写⼊,但不禁⽌读取。
  • func (rw *RWMutex) RUnlock()
    Runlock⽅法解除rw的读取锁状态,如果m未加读取锁会导致运⾏时错误。
  • func (rw *RWMutex) RLocker() Locker
    Rlocker⽅法返回⼀个互斥锁,通过调⽤rw.Rlock和rw.Runlock实现了Locker接⼝。
  1. 示例代码
func main() {
 var rwm sync.RWMutex
 for i := 1; i <= 3; i++ {
 go func(i int) {
 fmt.Printf("goroutine %d,尝试读锁定。。n", i)
 rwm.RLock()
 fmt.Printf("goroutine %d,已经读锁定了。。n", i)
 time.Sleep(5 * time.Second)
 fmt.Printf("goroutine %d,读解锁。。n", i)
 rwm.RUnlock()
 }(i)
 }
 time.Sleep(1*time.Second)
 fmt.Println("main..尝试写锁定。。")
 rwm.Lock()
 fmt.Println("main。。已经写锁定了。。")
 rwm.Unlock()
 fmt.Printf("main。。写解锁。。。") }
sync包中的条件变量Cond (⼀)、条件变量Cond
  1. 原型
    type Cond struct {
    noCopy noCopy
    // L is held while observing or changing the condition
    L Locker
    notify notifyList
    checker copyChecker
    }
    Cond实现了⼀个条件变量,⼀个线程集合地,供线程等待或者宣布某事件的发⽣。
    每个Cond实例都有⼀个相关的锁(⼀般是Mutex或RWMutex类型的值),它必须在改变条件时或者调⽤Wait⽅法时保持锁定。Cond可以创建为其他结构体的字段,Cond在开始使⽤后不能被拷⻉。条件变量:sync.Cond,多个goroutine等待或接受通知的集合地
  2. Cond中的⽅法
  • func NewCond(l Locker) Cond
    使⽤锁l创建⼀个Cond。Cond条件变量,总是要和锁结合使⽤。
  • func (c *Cond) Broadcast()
    Broadcast唤醒所有等待c的线程。调⽤者在调⽤本⽅法时,建议(但并⾮必须)保持c.L的锁定。
  • func (c *Cond) Signal()
    Signal唤醒等待c的⼀个线程(如果存在)。调⽤者在调⽤本⽅法时,建议(但并⾮必须)保持c.L的锁定。发送通知给⼀个⼈。
  • func (c *Cond) Wait()
    Wait⾃⾏解锁c.L并阻塞当前线程,在之后线程恢复执⾏时,Wait⽅法会在返回前锁定c.L。和其他系统不同,Wait除⾮被Broadcast或者Signal唤醒,不会主动返回。⼴播给所有⼈。
    因为线程中Wait⽅法是第⼀个恢复执⾏的,⽽此时c.L未加锁。调⽤者不应假设Wait恢复时条件已满⾜,相反,调⽤者应在循环中等待:
  1. 示例代码
func main() {
 var mutex sync.Mutex
 cond := sync.Cond{L:&mutex}
 condition := false
 go func() {
 time.Sleep(1*time.Second)
 cond.L.Lock()
 fmt.Println("⼦goroutine已经锁定。。。")
 fmt.Println("⼦goroutine更改条件数值,并发送通知。。")
 condition = true//更改数值
 cond.Signal() //发送通知:⼀个goroutine
 fmt.Println("⼦gorutine。。。继续。。。")
 time.Sleep(5*time.Second)
 fmt.Println("⼦groutine解锁。。")
 cond.L.Unlock()
 }()
 cond.L.Lock()
 fmt.Println("main..已经锁定。。。")
 if !condition{
 fmt.Println("main.。即将等待。。。")
 //wait()
 // 1.wait尝试解锁,
 // 2.等待--->当前的groutine进⼊了阻塞状态,等待被唤醒:signal(),broadcast()
 // 3.⼀旦被唤醒后,⼜会锁定
 cond.Wait()
 fmt.Println("main.被唤醒。。")
 }
 fmt.Println("main。。。继续")
 fmt.Println("main..解锁。。。")
 cond.L.Unlock()
}
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/965441.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号