Preface:
In a single thread, there is only one thread that operates on data, and only one thread participates in data modification. Data is relatively safe. When multi-threading, more than one thread operates on data, so it is inevitable that it will be disordered when modifying data at the same time.
1. What is a mutex?
1. Concept
Mutex is for concurrent security, in multiplegoroutine
When working together, it is very unsafe to write shared data when it is easily lost due to competition. Mutex locks are usually added to the place where shared data is modified.
2. Unlocked
- Thread is not safe, the operation of the global variable will calculate the exception
package main import ( "fmt" "sync" ) var x int = 0 var wg func add() { defer () for i := 0; i < 5000; i++ { x++ } } func main() { (2) go add() go add() () (x) } /* Print result: (Each printing is different, the normal result should be 10,000) 6051 5059 5748 10000 */
3. After locking
- Thread safety, global variable calculation without exception
package main import ( "fmt" "sync" ) var x int = 0 var wg // Create a lock objectvar lock func add() { defer () for i := 0; i < 5000; i++ { // Add lock () x++ //Unlock () } } func main() { (2) //Open two threads go add() go add() () (x) } /* Print result: All are 10,000 */
2. Read and write lock [Efficiency Revolution]
1. Why is the read and write lock efficient
When using locks, safety and efficiency often need to be converted to each other. When operating on data, only data will be read and written. Reading and reading can be performed simultaneously, and reading and writing need to ensure that you do not read when writing. At this time, in order to improve efficiency, a read-write lock was invented. Under the read-write lock mechanism, the safety did not decrease at all, but the efficiency was improved exponentially. The efficiency became more obvious when the number of read and write operations was greater.
2. How to use
The code is as follows (example):
package main import ( "fmt" "sync" "time" ) var ( x = 0 rwlock wg ) func write() { defer () () x++ () } func read() { () //Open the read lock () (x) //Release the read lock () } func main() { start := () for i := 0; i < 100; i++ { (1) go write() } // () for i := 0; i < 10000; i++ { (1) go read() } () (().Sub(start)) }
three,
Generate background
In multiplegoroutine
There are often conflicts in data reading and writing due to threads that are not synchronized. Especially when creating file opening objects, it may cause writing content to closed files, using uninitialized objects, or initializing an object multiple times.
Mechanism Overview
Ensure that the code in the function is executed only once. The implementation mechanism is that there is a flag bit inside once. After execution of the code, the flag bit will be set to 1 and the subsequent judgment flag bit. If the flag bit is changed to 1, it cannot be manipulated again.
Note
()
The function parameters passed in have no parameters and no return. A once object can only execute the Do method once. When multiple different functions are passed into the Do method, only the first one can be executed. The function passed in the Do method has no parameters and no return. You can use the function closure to pass the required variables into it.
4. How to use
- Generally used in concurrent use, aiming to close channels or files only once
func f2(a <-chan int, b chan<- int) { for { x, ok := <-a if !ok { break } (x) b <- x * 10 } // Make sure channel b is closed only once (func() { close(b) }) }
IV. Atomic atomic packet operation
The atomic packet performs secure addition and subtraction exchange operations on the specified data; there are also a lot of interested friends on the Internet who are interested in the atomic packet API to Baidu on their own, so I won't explain it in detail here.
package main import ( "fmt" "sync" "sync/atomic" ) var x int64 = 0 var wg /* Atomic operation is to package data and perform corresponding operations directly through the specified function. You can use load reading, store writing, add modification, and swap exchange. // Similar to reading a variable and assigning a variable */ func addone() { // If there is no locking for concurrency, data loss will occur defer () // x++ // You can use it without locking // The first parameter is the data for the operation, the second is the increase step length atomic.AddInt64(&x, 1) } func csf() { // If you compare equally, replace the new value with the old value ok := atomic.CompareAndSwapInt64(&x, 100, 200) (ok, x) } func main() { for i := 0; i < 50000; i++ { (1) go addone() } () (x) x = 100 csf() (123) }
Summarize:
Read and write locks distinguish between readers and writers, while mutexes do not distinguish between them. A mutex only allows one thread to access the object at the same time, regardless of read and write; a read and write lock allows only one writer at the same time, but allows multiple readers to read the object at the same time. Contact: The mechanism of read and write lock is similar to a mutex lock when acquiring a write lock.
This is the article about Go thread safety mutex and read and write locks. For more related contents of Go language mutex and 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!