Go Language Foundation-sync Package

Source: Internet
Author: User

Golang recommended communication and synchronization through the channel, but in the actual development of the sync pack is also very much, in the Ethereum source code also has a lot of this kind of application embodiment.
The Go Sync Pack offers: Sync. Mutex,sync. Rmutex,sync. Once,sync. Cond,sync. Waitgroup,sync.atomic, and so on, the text mainly on the use of Sync.mutex,sync.rmutex and Sync.waitgroup described, follow-up will introduce other methods of the use of instructions.

Sync contains a Locker interface:

type Locker interface {        Lock()        Unlock()}

The interface has only two methods, Lock () and Unlock (). The entire sync package is implemented around this interface.

Mutex Mutex

Mutex mutex is a concrete implementation of locker, there are two methods:

func (m *Mutex) Lock()func (m *Mutex) Unlock()

A mutex can only be locked by one goroutine at a time, and the other goroutine will block until the mutex is unlocked and then re-compete for the lock on the mutex.

Unlocking an unlocked mutex will result in a run-time error.

package mainimport (    "fmt"    "sync"    "time")func main() {    ch := make(chan struct{}, 2)    var l sync.Mutex    go func() {        l.Lock()        defer l.Unlock()        fmt.Println("goroutine1: 锁定大概 2s")        time.Sleep(time.Second * 2)        fmt.Println("goroutine1: 解锁了,可以开抢了!")        ch <- struct{}{}    }()    go func() {        fmt.Println("groutine2: 等待解锁")        l.Lock()        defer l.Unlock()        fmt.Println("goroutine2: 我锁定了")        ch <- struct{}{}    }()    // 等待 goroutine 执行结束    for i := 0; i < 2; i++ {        <-ch    }}

Read/write Lock Rwmutex

Read-write lock is for the read and write operation of the mutex, read-write and mutual exclusion lock the biggest difference is that read, write can be locked separately. Generally used in a large number of read operations, a small number of write operations:

func (rw *RWMutex) Lock()func (rw *RWMutex) Unlock()func (rw *RWMutex) RLock()func (rw *RWMutex) RUnlock()

Since there is a need to differentiate between read and write locks, the read-write lock defines:

    • Read lock (Rlock) to lock the read operation

    • Read Unlock (runlock), unlock read lock

    • Write lock (lock), which locks the write operation

    • Write Unlock (Unlock) to unlock the write lock

Do not mix locking and unlocking, such as: Lock and Runlock, Rlock, and Unlock. A run-time error is caused by a read or write lock on an unread lock, or a written lock on a read-write lock that is not written.

How do you understand read-write locks?

    • Only one goroutine can get a write lock at the same time.

    • You can also have any number of Gorouinte to obtain a read lock.

    • Only write locks or read locks (read and write mutexes) can exist at the same time.

That is, when a goroutine gets a write lock, the rest of the read lock or write lock will block until the write is unlocked, and when one of the goroutine gets a read lock, the other read locks can still continue; when there is one or any number of read locks, The write lock waits for all read locks to be unlocked before a write lock can be made. So the read lock (rlock) purpose here is actually to tell the write lock: There are a lot of people reading the data, you need to wait until they read (read unlock) and then write (write lock).

package mainimport (    "fmt"    "math/rand"    "sync")var count intvar rw sync.RWMutexfunc main() {    ch := make(chan struct{}, 10)    for i := 0; i < 5; i++ {        go read(i, ch)    }    for i := 0; i < 5; i++ {        go write(i, ch)    }    for i := 0; i < 10; i++ {        <-ch    }}func read(n int, ch chan struct{}) {    rw.RLock()    fmt.Printf("goroutine %d 进入读操作...\n", n)    v := count    fmt.Printf("goroutine %d 读取结束,值为:%d\n", n, v)    rw.RUnlock()    ch <- struct{}{}}func write(n int, ch chan struct{}) {    rw.Lock()    fmt.Printf("goroutine %d 进入写操作...\n", n)    v := rand.Intn(1000)    count = v    fmt.Printf("goroutine %d 写入结束,新值为:%d\n", n, v)    rw.Unlock()    ch <- struct{}{}}

Waitgroup

Waitgroup is used to wait for a set of goroutine to end and usage is relatively straightforward. It has three methods:

func (wg *WaitGroup) Add(delta int)func (wg *WaitGroup) Done()func (wg *WaitGroup) Wait()

Add the number of Goroutine to be added. Done executes a quantity minus 1. Wait waits for the end:

package mainimport (    "fmt"    "sync")func main() {    var wg sync.WaitGroup    for i, s := range seconds {        // 计数加 1        wg.Add(1)        go func(i, s int) {            // 计数减 1            defer wg.Done()            fmt.Printf("goroutine%d 结束\n", i)        }(i, s)    }        // 等待执行结束    wg.Wait()    fmt.Println("所有 goroutine 执行结束")}

ATTENTION, WG. The ADD () method must be executed before Goroutine starts.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.