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

关于C#多线程中值类型set访问器的误导性 #645

Closed
shangfengh opened this issue May 28, 2023 · 3 comments
Closed

关于C#多线程中值类型set访问器的误导性 #645

shangfengh opened this issue May 28, 2023 · 3 comments
Labels
bug Something isn't working help wanted Extra attention is needed

Comments

@shangfengh
Copy link
Member

shangfengh commented May 28, 2023

Describe the bug

private int hp = 0;
public int HP
{
  get
  {
    lock (gameObjLock)
    return hp;
  }
  set
  {
    lock (gameObjLock)
    hp = value;
  }
}
private int hp = 0;
public int HP
{
  get => Interlocked.CompareExchange(ref hp, -1, -1);
  set => Interlocked.Exchange(ref hp, value);
}

在多线程中,通常要对set与get访问器加锁或采用原子操作保证安全,但是这并不能保证完全安全合理
例如HP+=3;就是显然的错误
其相当与先调用get,再调用set,中间插入set操作将导致结果错误

这样可能导致set访问器具有误导性

Expected behavior
目前我进行中的修改方法是单独编写set或add方法
clgg建议可以采用结构体/类的方式来解决

应当令HP+=3;的写法在语法上不成立或者能够安全地编译
这个问题应该并非没有先例,想知道有什么更优雅的解决方案

Additional context
本issue与这个issue相关,但你不需要查看这个issue

@Timothy-Liuxf
Copy link
Member

Timothy-Liuxf commented May 28, 2023

+= 确实不能保证原子。可以封装出一些方法来做诸如 AddHp,而取消 set 访问器。

对于这点,C++ 的方案是封装成泛型类,比如原子的 int 就是 std::atomic<int>,一切操作均封装在它的成员函数内。像 Go 语言,就是和 C# 的 Interlocked 一样。

@shangfengh shangfengh added bug Something isn't working help wanted Extra attention is needed labels May 28, 2023
@shangfengh
Copy link
Member Author

将采用结构体的方式解决该问题

@shangfengh
Copy link
Member Author

改为使用类解决这个问题,结构体过于不便

@shangfengh shangfengh linked a pull request Jul 9, 2023 that will close this issue
4 tasks
@shangfengh shangfengh removed a link to a pull request Jul 9, 2023
4 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working help wanted Extra attention is needed
Projects
None yet
Development

No branches or pull requests

2 participants