我面临的问题是,我有一个在某些线程之间共享的 C# (.NET) 对象。线程可能会用另一个对象替换该对象。使用异步框架从 TCP/IP 连接中唤醒线程。
序列:
线程(等待连接)-> 异步回调-> 做一些线程安全的事情-> 访问共享对象 -> 做一些线程安全的事情。
1。解决方案互斥:
Object sharedObject = new Object();
Mutex objectMutex = new Mutex();
void threadCallback()
{
Object newObject = new Object();
// some processing
objectMutex.lock();
// do exchange sharedObject with newObject if needed
// very little processing here
objectMutex.unlock();
// some processing
}
2。解联锁
Object sharedObject = new Object();
int usingSharedObject = 0;
void threadCallback()
{
Object newObject = new Object();
// some processing
// poll until we lock
while(1 == Interlocked.Exchange(ref usingSharedObject , 1))
{
// do exchange sharedObject with newObject if needed
// very little processing here
Interlocked.Exchange(ref usingSharedObject , 0); // free lock
}
// some processing
}
什么速度更快,扩展性更好?
只要没有太多线程同时轮询,我希望第二种解决方案会更快。第二种解决方案甚至可以休眠一个随机时间,这样轮询就不会占用任何处理时间。如果我真的需要处理大量 TCP/IP 连接,第一个解决方案对我来说看起来更清晰。由于我在有关 TCP/IP 处理的锁定部分中做的处理很少,是否会有任何放大问题?
threadCallback()函数开头的对象创建怎么样
在我的 C++ 背景下,我总是在这种情况下使用内存池,因为我必须使用安全的 .NET 有没有一种快速创建新对象的方法,或者 .NET 平台在这个领域是否表现良好。
最好的问候,
弗里德里希
最佳答案
您的联锁操作不正确。自旋锁通常看起来像这样:
int sharedLock = 0;
void callback()
{
do {
int existingState = Interlocked.CompareExchange(ref sharedLock, 1, 0);
if (0 == existingState) {
break;
}
} while (true);
try
{
// operate on the shared state
}
finally
{
int existingState = Interlocked.Exchange(ref sharedLock, 0);
Debug.Assert (1 == existingState);
}
至于使用一个还是另一个的原因,主要取决于持有锁时执行的操作类型。非常短的操作(短算术加/减、简单的状态标志更改等)更适合自旋锁。繁重的操作(分配、IO 访问)不能在自旋锁下发生,因此它们必须在真正的互斥锁下完成。
关于c# - 互锁与互斥,放大问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2193435/