SoFunction
Updated on 2025-04-07

Golang The specific implementation of concurrent read and write lock

1. Overview of Go language concurrent read and write locks

In concurrent programming in Go language, it is an extremely important synchronization primitive, which is used to coordinate concurrent access to shared resources by multiple coroutines. Through a reasonable locking mechanism, it effectively balances the relationship between the concurrency performance of read operations and the data consistency guarantee, allowing multiple coroutines to perform read operations at the same time, but maintains exclusiveness during write operations to prevent data competition and inconsistency.

2. Function list of concurrent read and write locks

  • Read lock (RLock): Multiple coroutines can acquire read locks at the same time, realizing concurrent reading of shared resources without blocking each other.
  • Release read lock (RUnlock): Used to release the acquired read lock resource and must be used in pairs with RLock to ensure the correct management and release of the lock resource.
  • Write lock: When a coroutine needs to modify a shared resource, a write lock is acquired. Write locks are exclusive. At the same time, only one coroutine is allowed to hold a write lock. During this period, the read and write operations of other coroutines will be blocked.
  • Release the write lock: Paired with Lock, release the write lock resource after completing the write operation, allowing other coroutines to continue accessing the shared resource.

3. Detailed analysis and examples of each function

(I) Read lock (RLock) and release read lock (RUnlock)

Function description

  • RLock enables coroutines to acquire read locks. When multiple coroutines hold read locks at the same time, they can read shared resources concurrently without conflict. This mechanism greatly improves the concurrency performance of read operations and is suitable for scenarios where more reads and less writes.
  • RUnlock is responsible for releasing the acquired read lock to ensure that the lock resources can be reasonably utilized by other coroutines. If the read lock is not released correctly, it may cause blockage or deadlock when the subsequent coroutine acquires the read lock.

Sample code

package main

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

var (
   rwMutex 
   sharedData int
)

func readData(id int) {
   () // Acquire the read lock, allowing multiple coroutines to enter and read shared data at the same time   defer () // Release the read lock at the end of the function to ensure that the resource is released correctly
   ("The coroutine %d is reading data, the current data value is: %d\n", id, sharedData)
}

func main() {
   sharedData = 10
   var wg 
   for i := 0; i < 5; i++ {
       (1)
       go func(id int) {
           defer ()
           readData(id)
       }(i)
   }
   ()
}

Note: In the above example, the readData function represents a coroutine operation that reads shared data. () allows multiple coroutines to enter the read data concurrently, while defer () ensures that the read lock can be correctly released regardless of whether the function ends normally or exits due to an exception.

(2) Write lock (Lock) and release write lock (Unlock)

  • Function description
  • Lock is used to acquire a write lock. When a coroutine acquires a write lock, it has exclusive access to the shared resources. At this time, the read and write operations of other coroutines will be blocked until the write lock is released. This exclusivity ensures that the data integrity and consistency of shared resources are not corrupted during the write operation.
  • Unlock is used to free write lock resources, allowing other coroutines to continue accessing shared resources and restore concurrent read and write operations. If the write lock is not released, it will cause blockage of the entire concurrent system, seriously affecting the performance and availability of the program.
  • Sample code
package main

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

var (
   rwMutex 
   sharedData int
)

func writeData(id int) {
   () // Obtain write lock and exclusive shared resource modification permissions   defer () // Release the write lock at the end of the function, allowing other coroutines to continue accessing
   sharedData = id * 10
   ("Coecho %d writes data, the new data value is: %d\n", id, sharedData)
}

func main() {
   var wg 
   for i := 0; i < 3; i++ {
       (1)
       go func(id int) {
           defer ()
           writeData(id)
       }(i)
   }
   ()
}

Note: In the writeData function, () ensures that only one coroutine can modify sharedData at the same time, and defer () releases the lock resource in time after the write operation is completed to avoid long-term blockage of other coroutines.

(III) The mutually exclusive relationship of read and write locks is reflected

Function description

  • The core mutually exclusive relationship of read and write locks is manifested as: the write operation and write operation are mutually exclusive, ensuring that only one write operation is in progress at the same time; the write operation and read operation are also mutually exclusive. When the write operation is in progress, the read operation must wait, and vice versa. This mutual exclusion mechanism ensures the data consistency and integrity of shared resources in a concurrent read and write environment.

Sample code

package main

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

var (
   rwMutex 
   sharedData int
)

func readData() {
   ()
   defer ()
   ("Reading data, value: %d\n", sharedData)
}

func writeData() {
   ()
   defer ()
   sharedData++
   ("Written data, data has been updated")
}

func main() {
   var wg 
   (2)
   go func() {
       defer ()
       readData()
   }()
   go func() {
       defer ()
       writeData()
   }()
   ()
}

Note: A read operation coroutine and a write operation coroutine are started in the main function. When the write operation coroutine acquires the write lock, the read operation coroutine will be blocked at () until the write operation is completed and the write lock is released, and the read operation can continue to be executed, which clearly shows the mutually exclusive characteristics of the read and write lock.

4. Summary

Applicable scenarios:

  • RLock: suitable for scenarios where shared resources are frequently read and the reading process will not modify the resources. For example, in a news website, the browsing counting reading operation of multiple articles can use a read lock, and a large number of concurrent readings will not interfere with each other and can be carried out efficiently.
  • Lock: Used when modifying shared resources is required. For example, in database transactions, write operations such as updating and deleting a record must be exclusive. At this time, use a write lock to prevent other coroutines from reading and writing simultaneously, causing data confusion.

Pros and cons:

  • RLock:

  • Advantages: allows multiple coroutines to hold read locks at the same time for concurrent reading, greatly improving the concurrent performance of read operations, and significantly improving the overall system throughput in scenarios such as more read and less write.

  • Disadvantages: If the read lock is used improperly, such as holding the read lock for a long time without releasing it, it will cause the write lock to be unable to obtain, which will cause the write operation to block for a long time and affect the timely update of data.

Lock:

  • Advantages: Ensure the exclusiveness of write operations, ensure the data integrity and consistency of shared resources during the modification process, and effectively avoid error results caused by data competition.

  • Disadvantages: Only one coroutine can hold a write lock at the same time, and whether it is a read operation or other write operations will be blocked. In scenarios where write operations are frequent, the concurrency performance of the system will be seriously reduced, resulting in overall inefficiency.

Through detailed analysis of the functions, applicable scenarios and advantages and disadvantages of read locks and write locks in concurrent read and write locks in Go language, developers can more accurately select appropriate lock mechanisms based on actual needs, thereby efficiently and securely handling the access of shared resources in concurrent programming.

This is the introduction to this article about the specific implementation of Golang concurrent read and write locks. For more related contents of Golang concurrent read and write locks, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!