Concurrency safety is the most basic common sense, but also the most easily ignored premise, more test an engineer language fundamentals and code specification.
Concurrent access to modify variables can lead to a variety of unpredictable results, the most serious is the program panic, such as the common go language map concurrent read/write panic
.
Let’s start with a few examples, the old cliché case, and how to avoid it.
String modification
The following is an example of a concurrent read/write string.
|
|
A goroutine repeatedly assigns the variable s, while another main reads the variable s. If it finds that the string reads “WHAT”, it initiates a panic.
After running the above code, it is destined to panic, the subjective intention of the code is that string assignment is atomic, either F*CK
, or WHAT THE
, why would WHAT
appear?
|
|
In go, strings are represented by the structure StringHeader
, which is clearly written in the source code as non-concurrent safe, so if there happens to be another goroutine that only changes the uintptr but not the Len when reading the string, then the above problem will occur.
Interfaces
Let’s take another example of the error interface, from our POI team. Without the context, it is essentially a panic caused by concurrent changes to the error variable.
|
|
The recurrence case is actually the same.
|
|
Take a look at the definition of an interface in the go language.
The reasoning is exactly the same, as long as there are concurrent reads and writes, there will be a so-called partial write.
Look at rust
This is a piece of rust entry-level code that will run with the following error.
|
|
Because the variable a has been moved, the program can no longer use the variable. This is the concept of rust ownership. The above mentioned problem is avoided at the compiler level, but the rust learning curve is too steep.
How to ensure security
There are many levels to talk about this
language
In simple terms, one big lock is enough, one is not enough, there are 100 segmented locks … for example, statsd agent, because a single agent has a big lock, create more agents on the line, synchronous can not, then switch to asynchronous …
A lot of code is not strict enough to a lock to seriously reduce the performance of the program, in order to program correctly, do not optimize prematurely. Especially business code, performance can not asg expand the heap of machines.
CI/CD
rely on the tool’s linter hint can do some display of the check, including the irregular code or something, are available. But after all, it is not rust compiler check, in fact, the compiler is not omnipotent.
engineer
In the old days, c/c++ programmers knew for every line of code they wrote how variables passed in and out were constructed and destructured, otherwise they wouldn’t even know about memory leaks.
Now the more advanced language, comes with gc brings development efficiency, but does not mean that engineers can not think. If that’s the case, isn’t it true that one day AI will be able to replace programmers, as if yes…
Maybe this is the impossible triangle of high-level languages, development efficiency, mind burden, runtime safety.