SoFunction
Updated on 2025-03-05

Example analysis of golang concurrency security and read-write mutex lock

Concurrent security and locking

Sometimes there may be multiple goroutines in Go code that operate a resource (critical area) at the same time, and this situation will cause a race problem (data race). Examples in real life include crossroads being competed by cars in all directions; and bathrooms on trains being competed by people in cars.

For example:

var x int64
var wg 
func add() {
    for i := 0; i < 5000; i++ {
        x = x + 1
    }
    ()
}
func main() {
    (2)
    go add()
    go add()
    ()
    (x)
} 

In the above code, we have enabled two goroutines to accumulate the value of the variable x. When these two goroutines access and modify x variables, there will be data competition, resulting in the final result that does not match the expected ones.

Mutex lock

import (
	"fmt"
	"sync"
)
var lock 
() // Add lock() // Unlock

Mutex is a commonly used method to control access to shared resources. It can ensure that only one goroutine can access shared resources at the same time. The Mutex type of the sync package is used in Go language to implement mutex locks. Use mutex to fix the problem with the above code:

var x int64
var wg 
var lock 
func add() {
    for i := 0; i &lt; 5000; i++ {
        () // Add lock        x = x + 1
        () // Unlock    }
    ()
}
func main() {
    (2)
    go add()
    go add()
    ()
    (x)
} 

Using a mutex can ensure that there is only one goroutine at the same time and only one goroutine enters the critical area, while other goroutines are waiting for the lock; when the mutex is released, the waiting goroutine can acquire the lock and enter the critical area. When multiple goroutines are waiting for a lock at the same time, the awakening strategy is random.

Read and write mutex lock

import (
	"fmt"
	"sync"
)
var rwlock 
()   // Write lock() // Unwrite lock

Mutex locks are completely mutually exclusive, but in many practical scenarios, there are more reads, fewer writes, and there is no need to add locks when we read a resource concurrently without involving resource modification. In this scenario, using reads, writes, locks are a better choice. Read and write locks use the RWMutex type in the sync package in Go language.

There are two types of read and write locks: read and write locks. When a goroutine acquires the read lock, other goroutines will continue to acquire the lock if they acquire the read lock, and if they acquire the write lock, they will wait; when a goroutine acquires the write lock, other goroutines will wait whether they acquire the read lock or the write lock.

Read and write lock example:

var (
    x      int64
    wg     
    lock   
    rwlock 
)
func write() {
    // () // Add mutex lock    () // Write lock    x = x + 1
    (10 * ) // Assuming that the read operation takes 10 milliseconds    ()                   // Unwrite lock    // () // Unlock mutex    ()
}
func read() {
    // () // Add mutex lock    ()               // Add reading lock    () // Assuming that the read operation takes 1 millisecond    ()             // Interpret lock    // () // Unlock mutex    ()
}
func main() {
    start := ()
    for i := 0; i &lt; 10; i++ {
        (1)
        go write()
    }

    for i := 0; i &lt; 1000; i++ {
        (1)
        go read()
    }
    ()
    end := ()
    ((start))
}

It should be noted that read and write locks are very suitable for scenarios where more reads and less reads. If the difference between read and write operations is not large, the advantages of read and write locks cannot be exerted.

The above is the detailed content of the example analysis of golang concurrency security and read-write mutex locks. For more information about golang concurrency security and read-write mutex locks, please pay attention to my other related articles!