This is a creation in Article, where the information may have evolved or changed.
Recently learned the mutex, read-write lock, Once, waitgroup in the Go language in the synchronization package. In the process of concurrent program development, these two kinds of locks are very important, including the time of access control for shared resources. Sync is the standard library in the Go language.
Mutex Mutex
- Mutex is the main means for traditional concurrent programs to control access to shared resources. Is the mutex structure in the sync package.
- The structure consists of two methods, which can be said to be very simple to use
func (m *Mutex) Lock() {}
func (m *Mutex) Unlock() {}
- Let's use a simple example to illustrate his usage:
123456789101112131415161718192021222324252627282930313233343536373839 |
PackageMainImport("Sync""FMT")typeSafecounterstruct{NumberintSync. Mutex} func (sc *safecounter) Increment() {SC. Lock () sc.number++sc. Unlock ()} func (sc *safecounter) decrement() {SC. Lock () Sc.number--sc.unlock ()} func (sc *safecounter) getnumber() int {SC. Lock () Number: = Sc.numbersc.Unlock ()returnNumber func main() {SC: =New(Safecounter) forI: =0; I < -; i++ {GoSc. Increment ()GoSc. Decrement ()}fmt. Println (Sc.getnumber ())} |
- The above example uses a mutex to ensure that the number integer variable is continuously and stably outputting 0 of the result in the case of Goroutine. Of course you can try to remove the lock protection, whether you can also stabilize the output 0?
Rwmutex Read/write lock
A read-write lock is a mutex for read and write operations. Follow these two principles
- Can be read casually, and support multiple goroutine to read simultaneously
- When you write, you can neither read nor write.
Rwmutex provides four methods
Func (*rwmutex) Lock
Func (*rwmutex) Unlock
Func (*rwmutex) Rlock
Func (*rwmutex) Runlock
An example of reading and writing a map illustrates how Rwmutex is used:
12345678910111213141516171819202122232425262728293031323334353637383940 |
PackageMainImport("FMT""Math/rand""Sync""Time")typeMapcounterstruct{mMap[int]intSync. Rwmutex} func (mapcounter *mapcounter) Reader(n int) { for{Mapcounter.rlock () V: = Mapcounter.m[rand. INTN (n)]mapcounter.runlock () fmt. Println (v) time. Sleep (1* Time. Second)}} func (mapcounter *mapcounter) Writer(n int) { forI: =0; I < n; i++ {mapcounter.lock () mapcounter.m[i] = i *TenMapcounter.unlock () time. Sleep (1* Time. Second)}} func main() {mc: = Mapcounter{m: Make(Map[int]int)}GoMc. Writer (Ten)GoMc. Reader (Ten)GoMc. Reader (Ten) time. Sleep ( the* Time. Second)} |
Once
- Once, as the name implies, is executed only once. With a simple example, you can explain:
1234567891011121314151617181920212223242526 |
PackageMainImport("FMT""Sync") func main() {once: = Sync. Once{}done: = Make(Chan BOOL) forI: =0; I <Ten; i++ {Go func() {once. Do (SayHello) done <-true}()} forI: =0; I <Ten; i++ {fmt. Println (<-done)}} func sayHello() {FMT. Println ("Hello")} |
- The above example only outputs a "Hello" and the rest is true.
Waitgroup
The
- Waitgroup can be a Goroutine collection, and the Waitgroup will automatically end when the Goroutine in the collection has finished executing. You can define the size of this waitgroup. There are only three methods in him:
- func (WG *waitgroup) Add (delta int) {}//define size
- func (WG *waitgroup) Done () {}
- func (WG *waitgroup) Wait () {}
- specific usage, illustrated by the following small example.
12345678910111213141516171819202122
|
package mainimport ( Span class= "string" > "FMT" ) func main () {wg: = sync. Waitgroup{}for i: = 0 ; I <= 5 ; i++ {WG. ADD (1 ) go Func (i int ) {defer WG. Done () fmt. Println ( "work done for" , I)} (i)}WG. Wait ()} |
- We recommend that you run the code above to make it easier for you to understand the meaning of the code. It's easier to understand it with official documents.
Reference
- Https://gowalker.org/sync More information please refer to the documentation