Difference between Value Type and Reference Type of Lock in golang

  golang, question

Mutex is introduced into the object to ensure atomicity, but when the object is a value reference, it is found that the cable has no effect. What is the internal logic of its implementation?

The code is as follows:

package main
 
 import (
 "fmt"
 "sync"
 )
 
 //The object is declared here
 type people struct {
 sync.Mutex
 }
 
 //Method of its value type
 func (p people) test(str string) {
 p.Lock();
 defer p.Unlock();
 
 for i := 0;   i < 5;  {
 fmt.Println(str, i)
 i++
 }
 }
 
 func main() {
 var user people
 var wg sync.WaitGroup
 
 wg.Add(2)
 go func() {
 defer wg.Done()
 user.test("go1")
 }()
 
 go func() {
 defer wg.Done()
 user.test("go2")
 }()
 
 wg.Wait()
 }

If you do this, you cannot see the effect, and then add this line of code:

func (p people) test(str string) {
 p.Lock();
 defer p.Unlock();
 
 for i := 0;   i < 5;  {
 fmt.Println(str, i)
 
 //Add the code here!  Here!
 time.Sleep(time.Second)
 i++
 }
 }

The findings of the implementation are as follows:

go2 0
 go1 0
 go2 1
 go1 1
 go1 2
 go2 2
 go2 3
 go1 3
 go1 4
 go2 4

Doubt point: in the whole logic process, there is only one variable user, and there is no process of value copying. how can a good lock not take effect?

First of all, mutex cannot be copied. once mutex is copied, locking and unlocking will act on different mutex objects, naturally losing the effect.

In addition, for the receiving object of the method, there is an essential difference between the receiver’s value and the pointer:
1. When the receiver is a pointer, the function call passes the pointer of the object.
2. When the receiver is a value, the function call passes a copy of the value.
This can be verified by changing the value of an object in a function call.

Therefore, when the people object makes a function call, people has copied the new value and generated a new mutex, so the lock is invalid. here, just change the receiver of test method to *people.