SoFunction
Updated on 2025-03-05

How to improve the efficiency of Go concurrency and locking

Concurrency security means that multiple concurrent bodies access the same shared data within the same period of time, and the shared data can be processed correctly.

Concurrent programming in many languages ​​is easy to make errors when modifying a variable at the same time, because the operation is not atomic, such as the variable used by an addition operation is modified, resulting in errors in the calculation result, which is typical for statistics on commodity inventory.

Personally, I suggest that all shared variables are usedchannel,becausechannelA mutex lock is used in the source code, which is concurrently safe.

We can not use it, but we must not misunderstand it. We are not panic when we have food in our hands.

Examples of concurrency insecurity

Arrays are concurrently unsafe, we need to know before the example begins.appendThe behavior of the function: the length is enough in the original arraycapAppend functions to addlen, if the length is not enough, the capacity expansion will be triggered and a new array will be applied for.capDouble the assignment migration.

Therefore, in this process, if you only discuss the expansion operation, there may be cases of simultaneously applying and assigning values, resulting in the missed data of an expansion increase.

var s []int

func appendValue(i int) {
	s = append(s, i)
}

func main() {
	for i := 0; i < 10000; i++ { //10000 coroutines add slices at the same time		go appendValue(i)
	}
    (2)
    (len(s))
}

For example,10000A coroutine adds data to the slice at the same time. You can try to run it, and the printed one must be not10000

  • The same resource for the above concurrent operation is calledCritical Zone
  • Because there is data competition in concurrent operations, the data value is accidentally rewritten, and the final result does not match the expected ones. This problem is collectively calledCompetition issues

It is common in controlling commodity inventory reduction, controlling balance increase and decrease. So is there any way to solve the competition problem?

  • Mutex: When accessing a critical area, there is only onegoroutineAvailable to access.
  • Atomic operations: Let certain operations become atoms, this follow-up discussion.

These two ideas run through countless high-concurrency/distributed solutions, whether they are used in a process application or implemented with the help of some third-party means, such as middleware. The Dugu Nine Sword Forest must be remembered firmly.

Mutex lock

GoThe usage of mutex locks in languages ​​is as follows:

var lock  //Mutual Exclusion Lock() // Add locks = append(s, i)
() //Unlock

Adding a mutex before and after accessing the critical area can ensure that there will be no concurrency problems.

We modified it or the previous one4.7.1Examples of adding mutex to it.

var s []int
var lock 

appendValueSafe := func(i int) {
    ()
    s = append(s, i)
    ()
}

for i := 0; i < 10000; i++ { //10000 coroutines add slices at the same time    go appendValueSafe(i)
}
(2)
(len(s))
  • Shared variablessThe write operation plus a mutex lock ensures that there is only one at the same timegoroutineModify content.
  • After locking and before unlocking, there is only one access at the same time, regardless of read or write.
  • No matter how many times it is output10000, there will be no competition problems again.
  • Note:If there is a concurrent read operation while writing, in order to prevent half of the data being read, you need to add a lock to the read operation.

Read and write lock

Mutex locks are completely mutually exclusive. There will be no problem if concurrent reads are not modified. There is no need to add locks during concurrent reads, otherwise the efficiency will be lower.

usage:

rwlock 
//Read lock()
()

//Write lock()
()

Concurrent reading is not mutually exclusive, and when a write lock is acquired, all other locks are waiting. The formula: reading is not mutually exclusive, reading is mutually exclusive, and writing is mutually exclusive. For specific calculations of speed, see the source code of 4.7.3. If you are interested, you can change the comment position and see that the efficiency has been significantly improved.

summary

  • Several nouns have been learned: critical section, competitive problem, mutex lock, atomic operation, read and write lock.
  • Mutex:, Read and write lock:AllsyncPacked.
  • Read and write locks are more efficient than mutex locks.

Question: Is it okay to just add a lock? Why?

Summarize

This is the article about how to improve the efficiency of Go concurrency and lock. For more information about Go concurrency and lock, please search for my previous articles or continue browsing the relevant articles below. I hope everyone will support me in the future!