9.1 basic knowledge
Locking and unlocking of write operations, referred to as "write locking" and "write unlocking":
func (*RWMutex)Lock() func (*RWMutex)Unlock()
Locking and unlocking of read operations are referred to as "read locking" and "read unlocking":
func (*RWMutex)RLock() func (*RWMutex)RUnlock()
Take an example of not using locks:
func printer(str string) { for _, data := range str { fmt.Printf("%c", data) } fmt.Println()}func person1() { printer("hello")}func person2() { printer("world")}func main() { go person1() person2()time.Sleep(time.Second)}//Output result / / worldhello / / LD
Examples of adding mutexes:
var mut sync.Mutexfunc printer(str string) { mut.Lock() defer mut.Unlock() for _, data := range str { fmt.Printf("%c", data) } fmt.Println()}func person1() { printer("hello")}func person2() { printer("world")}func main() { go person1() person2()time.Sleep(time.Second)}//Output result / / world//hello
9.2 precautions
9.2. 1 mutex
-
Don't Lock the mutex repeatedly: locking a locked mutex will immediately block the current goroutine, and the process executed by the goroutine will always stop on the line of code calling the Lock method of the mutex. (Note: the panic thrown by the Go language runtime system is fatal and cannot be recovered. Calling the recover function has no effect on them. In other words, once a deadlock occurs, the program will crash.)
-
Don't forget to unlock the mutex. Use the defer statement if necessary: operations such as "lock, unlock, re lock and re unlock" may occur in the process executed by a goroutine. Therefore, if we forget the unlocking operation in the middle, it will cause repeated locking.
var mutex sync.Mutex func write() { defer mutex.Unlock() // Unlock mutex through defer Lock() / / obtain critical resources and execute specific logic...}
-
Do not unlock a mutex that has not been locked or unlocked: This program will directly panic.
var mutex sync.Mutex // Define mutex mutex Lock()mutex. Unlock()mutex. Unlock() // fatal error: sync: unlock of unlocked mutexreturn
-
Do not directly pass a mutex between multiple functions: a mutex is a structure type, that is, a value type. Passing it to a function, returning it from a function, assigning it to other variables, and letting it enter a channel will lead to the generation of its copy. Therefore, the original value and its copies, as well as multiple copies, are completely independent, and they are different mutexes.
9.2. 2. Read write lock
-
Attempting to lock the write lock after the write lock has been locked will block the current goroutine;
-
Attempting to lock the read lock when the write lock is locked will also block the current goroutine;
-
Attempting to lock the write lock when the read lock is locked will also block the current goroutine;
-
Attempting to lock the read lock after the read lock has been locked will not block the current goroutine;
-
Unlocking the "write lock not locked in the read / write lock" will immediately trigger panic, and the same is true for the read lock.
It's a bit wordy. I'll summarize it in Vernacular: when I read the data, you can read it, because the data of my two are the same; When I read data, you can't write. When you write, the data changes. I still read a ghost; When I write data, you can't read or write. I'm so strong. Here is an example:
var count intvar mutex sync.RWMutexfunc write(n int) { rand.Seed(time.Now().UnixNano()) fmt.Printf("write goroutine %d Writing data...\n", n) mutex.Lock() num := rand.Intn(500) count = num fmt.Printf("write goroutine %d Write data end, write new value %d\n", n, num) mutex.Unlock()}func read(n int) { mutex.RLock() fmt.Printf("read goroutine %d Reading data...\n", n) num := count fmt.Printf("read goroutine %d End of reading data, read %d\n", n, num) mutex.RUnlock()}func main() { for i := 0; i < 10; i++ { go read(i + 1) } for i := 0; i < 10; i++ { go write(i + 1) } time.Sleep(time.Second*5)}//Output result goroutine 1 reading data Reading goroutine 1, reading data, reading 0, reading goroutine 7, reading data Reading goroutine 7 finished reading data, read 0, reading goroutine 3 reading data Read goroutine 3, read data, read 0, read goroutine 10, reading data Reading goroutine 10 finished reading data, reading 0, reading goroutine 8 reading data Read goroutine 8, read data, read 0, read goroutine 6, reading data Goroutine 5 reading data Read goroutine 5, read data, read 0, write goroutine 2, writing data Goroutine 4 reading data Reading goroutine 4 finished reading data, read 0 and write goroutine 4 is writing data Write goroutine 3 writing data Goroutine 2 reading data Read goroutine 2, read data, read 0, write goroutine 9, writing data Read goroutine 6, read data, read 0, write goroutine 7, writing data Goroutine 9 is reading data Read goroutine 9, read data, read 0, write goroutine 6, writing data Write goroutine 1 writing data Write goroutine 8 writing data Write goroutine 10 writing data Write goroutine 5 writing data Write goroutine 2 write data, write new value 365 write goroutine 4 write data, write new value 47 write goroutine 3 write data, write new value 468 write goroutine 9 write data, write new value 155 write goroutine 7 write data, write new value 112 write goroutine 6 write data, write new value 490 write goroutine 1 Write data, Write new value 262, write goroutine 8, write data, write new value 325, write goroutine 10, write data, write new value 103, write goroutine 5, write data, and write new value 353
It can be seen that the first 10 coroutines can read data in parallel, and the last 10 coroutines are all blocked in "... Writing data..." Process, after reading, then 10 collaborative processes will start to be written in turn.
9.3 summary
There is not much content in this chapter. We mainly need to pay attention to several precautions of mutex lock and read-write lock. Read-write lock is actually a finer grained lock division. In order to make the program more concurrent, it has been described very clearly above, so I won't be verbose here. The only point to emphasize again is that we should not try to unlock an unlocked lock, whether it is a mutex lock or a read-write lock, because this will cause an unrecoverable panic.