【发布时间】:2019-09-06 06:00:42
【问题描述】:
我有一个代码库,其中多个线程正在写入ConcurrentDictionary,并且每隔 60 秒另一个线程运行并克隆主 CD,将其清除,然后继续在克隆的 CD 上工作。我想知道如果我不使用lock 而Cloning and Clearing 主CD,我会错过一些数据吗?演示问题的代码如下:
class Program
{
static object lock_obj = new object();
static async Task Main(string[] args)
{
ConcurrentDictionary<string, ThreadSafeLong> cd = new ConcurrentDictionary<string, ThreadSafeLong>();
Func<Task> addData = () =>
{
return Task.Run(async () =>
{
var counter = 1;
while (true)
{
lock (lock_obj)
{
for (int i = 0; i < 100_000; i++)
{
cd.TryAdd($"{counter}:{i}", new ThreadSafeLong(i));
//WriteLine(i);
}
WriteLine($"Round {counter}");
}
counter++;
await Task.Delay(1_000);
}
});
};
Func<Task> writeData = () =>
{
return Task.Run(async () =>
{
while (true)
{
var sw = Stopwatch.StartNew();
lock (lock_obj) // to clone the data, and prevent any other data to be added while clone
{
var cloned = new ConcurrentDictionary<string, ThreadSafeLong>(cd);
cd.Clear();
WriteLine($"Cloned Count: {cloned.Count}");
}
sw.Stop();
WriteLine($"Elapsed Time: {sw.ElapsedMilliseconds}");
await Task.Delay(6_000);
}
});
};
await Task.WhenAll(addData(), writeData());
}
}
PS:可能与here的问题有关
【问题讨论】:
-
所以你有多个生产者和一个消费者,但是消费者分批接收它的工作。专门使用字典来保存排队的请求批次有什么好处/要求?
-
我为每个键保留一个聚合值,我不希望每次点击都是单独的输入,所以我使用了字典,并且每次都增加值。
-
无竞争锁很便宜。只要你不持有锁太久,就可以了。努力减少您需要持有锁的时间,而不是试图完全移除它。
-
你为什么使用
ConcurrentDictionary?由于您在每次读写之前都会锁定,因此一个简单的Dictionary就足够了。 -
@TheodorZoulias,你是对的,最初的问题是如何克隆一个
ConcurrentDictionary,但是在我们完成了我的示例之后,就不再需要了。
标签: c# collections thread-safety clone concurrentdictionary