introduction
As mentioned earlier, mutex locks can be used when competing for resources, which ensures the uniqueness of resource access, but also reduces performance. If you analyze the scenario carefully, if you just read data, no matter how many goroutines there will be logical mutex operations.
Here, read and write lock🔐 RWMutex came into being, and RWMutex can lock and unlock read and write operations respectively.
RWMutex allows multiple read operations to be performed at the same time, but only one write operation is allowed. At the same time, when a certain write operation is performed, the read operation cannot be performed.
There are many ways to read and write locks
- Method 1: RLock This method is a read lock. When the write lock exists, the read lock cannot be loaded. It can only be used when there is no lock, or only when the read lock is read. Read locks can load multiple times at the same time, suitable for scenarios where there are more and less writing.
- Method 2: RUnlock This method is to read and unlock a single lock read operation.
- Method 3: Lock This method is to write lock. If there are other read locks and write locks before adding write locks, the lock will be blocked until it can be used.
- Method 4: Unlock This method is to write unlock. If you don’t bind the write lock, write unlock directly, which will cause a runtime error.
Read operation
Here is an example using actual code and take a look at the reading operation:
package main import ( "fmt" "sync" "time" ) //Create a new pointer to the lock object, and then create the lock object in the pointer later.var rwMutex * //In order to ensure that the child's goroutine is executed first, you can use the synchronous waiting group wg, and here to create the pointer type of wgvar wg * func main() { rwMutex = new() wg = new() (2)//Remember +add here // Start 2 goroutines in the main function go readData(1) go readData(2) () ("main func end") } func readData(i int) { defer () (i, "start locking!") // Lock the read operation () // Read data (i, "Reading data") // Sleep (1 * ) // Read unlock () //Print prompt information (i, "Read over") }
The code run results are as follows:
2 start locking!
2 Reading data
1 start locking!
1 Reading data
2 Read over
1 Read over
main func end
From the printing results, we can see that the second goroutine first read lock, then the second starts reading, and then the first read lock [from here, we can see that because the second read lock has not been read and unlocked, the first read lock is uploaded, so the read lock here is not mutually exclusive]. Then the first starts reading, the second read unlock, and the first read unlock. The main goroutine ends.
Write operation
package main import ( "fmt" "sync" "time" ) //Create a new pointer to the lock object, and then create the lock object in the pointer later.var rwMutex * //In order to ensure that the child's goroutine is executed first, you can use the synchronous waiting group wg, and here to create the pointer type of wgvar wg * func main() { rwMutex = new() wg = new() (4) // Start 2 goroutines in the main function go readData(1) go readData(2) go writeData(3) go writeData(4) () ("main func end") } func readData(i int) { defer () (i, "start locking!") // Lock the read operation () // Read data (i, "Reading data") // Sleep (1 * ) // Read unlock () //Print prompt information (i, "Read over") } func writeData(i int) { defer () (i, " Writing Start") //Write lock () (i, "~~~ writing right now~~~") (1 * ) () (i, "writing completed") }
The code run results are as follows:
2 start locking!
2 Reading data
4 Writing Start
1 start locking!
3 Writing Start
2 Read over
4 ~~~ writing right now~~~
4 writing completed
1 Reading data
1 Read over
3 ~~~ writing right now~~~
3 writing completed
main func end
According to analysis, goroutine3 only gets permission to start writing after goroutine4 is finished writing.
But to be honest, locks and unlocks are everywhere, critical areas, which are really bloated and prone to problems.
When multiple coroutines in the go language want to share data, they will have a more elegant way of processing.
The above is the detailed explanation of the Go read and write lock method example. For more information about Go read and write lock method, please pay attention to my other related articles!