Tho*_*mas 1 c# multithreading locking
在服务器应用程序上,我需要为每个连接的客户端分配一个唯一的ID,所以我这样做:
private short GetFreeID()
{
lock (this.mUsedPlayerIDsSynchronization)
{
for (short I = 1; I < 500; I++)
{
if (ClientIDPool[I] == false)
{
ClientIDPool[I] = true;
return I;
}
}
return -1;
}
}
Run Code Online (Sandbox Code Playgroud)
我的第一个问题:能否更有效地完成,我的意思是更好的表现?我在这里读过,我们应该学会编写没有锁的代码.我还在那里阅读了一些原子操作还有其他选择.第二个问题:如果我想锁定整个课程以便不允许在其中进行任何更改,该怎么办?例如:一个客户端将更新第二个客户端数据,我可以锁定它被绝对阻止的整个第二个客户端类吗?我仍然认为"锁定"只会确保其片段中的代码当时只被一个线程输入,所以我不知道"lock(client2)"是否导致该类中的任何内容都无法更改,直到此锁定为止释放.
Jon*_*eet 11
锁定通常是最简单的方法,这是非常重要的.通常,如果有更有效的处理方式并不重要,只要你有清晰的代码并且它的表现足够好.
但是,更高效的方法是生成随机GUID,或者如果您确实要重用ID,则LinkedList使用未使用ID 的"池"(例如a ).然后,您可以非常快速地从池中取出,并在完成后将ID返回池中(再次快速).
另外,如果你真的只需要一个整数,它不具备成为一个低之一,你可以有它从0开始,您只需每次增加一个静态变量-你可以做到这一点,而无需使用锁Interlocked.Increment,你应该希望.我怀疑你会耗尽64位整数,例如:)
至于你的第二个问题:是的,锁是建议性的.如果类中的所有内容在更改任何字段之前取出相同的锁(并且字段是私有的)那么这会阻止其他代码行为不端......但是每一段代码都需要取出锁.
编辑:如果你真的只需要一个整数,我仍然建议只使用Interlocked.Increment- 即使你的流量增加1000倍,你可以使用64位整数.但是,如果您想重用ID,那么我建议创建一个新类型来表示"池".给这多少计数器已经创建的,所以,如果你用完了,你可以指定一个新的项目.然后只将可用的存储在a中Queue<int>,LinkedList<int>或者Stack<int>(你使用它并不重要).假设您可以信任自己的代码以合理地返回ID,您可以使API简单如下:
int AllocateID()
void ReturnID(int id)
Run Code Online (Sandbox Code Playgroud)
AllocateID将检查池是否为空,如果是,则分配一个新ID.否则,它只会删除池中的第一个条目并返回该条目.ReturnID只会将指定的ID添加到池中.