Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

container/garray: MarshalJSON func unnecessary with RLock because it use value receiver #4133

Closed
ansionfor opened this issue Jan 22, 2025 · 12 comments
Labels

Comments

@ansionfor
Copy link
Member

Is your feature request related to a problem?

Option Yes

Describe the solution you'd like

The MarshalJSON method of the container/garray package uses a value receiver, so the data of the array will be copied. Therefore, there is no need to add an RLock.

Describe alternatives you've considered

before:

func (a Array) MarshalJSON() ([]byte, error) {
	a.mu.RLock()
	defer a.mu.RUnlock()
	return json.Marshal(a.array)
}

I suggest:

func (a Array) MarshalJSON() ([]byte, error) {
	return json.Marshal(a.array)
}

lets test:

func (a Array) MarshalJSON() ([]byte, error) {
	fmt.Println(fmt.Sprintf("before=%+v", a.array))
	time.Sleep(2 * time.Second)
	fmt.Println(fmt.Sprintf("after=%+v", a.array))
	return json.Marshal(a.array)
}

func TestArray_MarshalJSON(t *testing.T) {
	gtest.C(t, func(t *gtest.T) {
		array := garray.NewArrayFrom([]interface{}{1, 2, 3}, true)

		go func() {
			time.Sleep(1 * time.Second)
			array.Append(4)
		}()

		data, err := array.MarshalJSON()
		t.AssertNil(err)
		t.Assert(data, []byte(`[1,2,3]`))
	})
}

result: The data of the MarshalJSON method will not be affected by other concurrent goroutines.
Image

Additional

My pull request: #4132

@wanghaolonggit
Copy link

不加锁 不会出现数据竞争吗?

@Issues-translate-bot
Copy link

Bot detected the issue body's language is not English, translate it automatically. 👯👭🏻🧑‍🤝‍🧑👫🧑🏿‍🤝‍🧑🏻👩🏾‍🤝‍👨🏿👬🏿


Will there be no data competition without locking?

@ansionfor
Copy link
Member Author

不加锁 不会出现数据竞争吗?

MarshalJSON用的值接收器,数据会被复制一份,不会出现数据竞争,通过我的测试用例可以看出。不知道我的理解是否正确

@Issues-translate-bot
Copy link

Bot detected the issue body's language is not English, translate it automatically. 👯👭🏻🧑‍🤝‍🧑👫🧑🏿‍🤝‍🧑🏻👩🏾‍🤝‍👨🏿👬🏿


Without locking, will there be no data competition?

For the value receiver used by MarshalJSON, the data will be copied and there will be no data competition, as can be seen from my test cases. I don't know if my understanding is correct

@ansionfor
Copy link
Member Author

另一个问题是,我不确定为什么MarshalJSON要用值接收器,而不使用指针接收器,如果有人知道可以告知一下

@Issues-translate-bot
Copy link

Bot detected the issue body's language is not English, translate it automatically. 👯👭🏻🧑‍🤝‍🧑👫🧑🏿‍🤝‍🧑🏻👩🏾‍🤝‍👨🏿👬🏿


Another question is, I'm not sure why MarshalJSON uses a value receiver instead of a pointer receiver. If anyone knows, can you tell me?

@wanghaolonggit
Copy link

不加锁 不会出现数据竞争吗?

MarshalJSON用的值接收器,数据会被复制一份,不会出现数据竞争,通过我的测试用例可以看出。不知道我的理解是否正确

切片的底层 是数组的指针,指针被复制,数组还是同一个数组。

把time.Sleep(1 * time.Second) 去掉 检测-race 检测下

@Issues-translate-bot
Copy link

Bot detected the issue body's language is not English, translate it automatically. 👯👭🏻🧑‍🤝‍🧑👫🧑🏿‍🤝‍🧑🏻👩🏾‍🤝‍👨🏿👬🏿


Without locking, won't there be data competition?

For the value receiver used by MarshalJSON, the data will be copied and there will be no data competition, as can be seen from my test cases. I don't know if my understanding is correct

The underlying layer of the slice is a pointer to the array. The pointer is copied, but the array is still the same array.

Remove time.Sleep(1 * time.Second) and check with -race

@ansionfor
Copy link
Member Author

不加锁 不会出现数据竞争吗?

MarshalJSON用的值接收器,数据会被复制一份,不会出现数据竞争,通过我的测试用例可以看出。不知道我的理解是否正确

切片的底层 是数组的指针,指针被复制,数组还是同一个数组。

把time.Sleep(1 * time.Second) 去掉 检测-race 检测下

加上-race的确提示data race问题,但很奇怪,既然数组是同一个数组,为什么before跟after打印的结果都是123,after的结果不应该是1234吗

@Issues-translate-bot
Copy link

Bot detected the issue body's language is not English, translate it automatically. 👯👭🏻🧑‍🤝‍🧑👫🧑🏿‍🤝‍🧑🏻👩🏾‍🤝‍👨🏿👬🏿


Without locking, won't there be data competition?

For the value receiver used by MarshalJSON, the data will be copied and there will be no data competition, as can be seen from my test cases. I don't know if my understanding is correct

The bottom layer of the slice is the pointer of the array. The pointer is copied, but the array is still the same array.

Remove time.Sleep(1 * time.Second) and check with -race

Adding -race does prompt a data race problem, but it is very strange. Since the array is the same array, why are the results printed by before and after both 123? Shouldn't the result of after be 1234?

@wanghaolonggit
Copy link

不加锁 不会出现数据竞争吗?

MarshalJSON用的值接收器,数据会被复制一份,不会出现数据竞争,通过我的测试用例可以看出。不知道我的理解是否正确

切片的底层 是数组的指针,指针被复制,数组还是同一个数组。
把time.Sleep(1 * time.Second) 去掉 检测-race 检测下

加上-race的确提示data race问题,但很奇怪,既然数组是同一个数组,为什么before跟after打印的结果都是123,after的结果不应该是1234吗

不能确定哪个goroutine 先执行

@Issues-translate-bot
Copy link

Bot detected the issue body's language is not English, translate it automatically. 👯👭🏻🧑‍🤝‍🧑👫🧑🏿‍🤝‍🧑🏻👩🏾‍🤝‍👨🏿👬🏿


Without locking, won't there be data competition?

For the value receiver used by MarshalJSON, the data will be copied and there will be no data competition, as can be seen from my test cases. I don't know if my understanding is correct

The bottom layer of the slice is the pointer of the array. The pointer is copied, but the array is still the same array.
Remove time.Sleep(1 * time.Second) and check-race.

Adding -race does prompt a data race problem, but it is very strange. Since the array is the same array, why are the results printed by before and after both 123? Shouldn’t the result of after be 1234?

Unable to determine which goroutine executes first

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants