在我的项目中,有N个线程可以访问全局哈希表,这是不可避免的。所以我认为我应该使用一个无锁哈希表或其他东西。毕竟,我选择尝试其他东西,而不是无锁定哈希表,因为无锁定哈希通常用于特殊目的,不太容易使用。
我的想法是:
有N线程访问全局哈希表,所以我将哈希表拆分为M子哈希表,其中M=N。在任何时候,从M个子哈希表中选择N个子哈希表的所有线程的总和是pow(M,N),从M个唯一的子哈希表中选出N个子哈希值的总和是P(M,N),因此不存在竞争条件的比率是P(M,N)/pow(M,N)并且存在竞争条件比率是1-P(M,M)/pow),即1-M/(M-N)/pow(M,N)。
我的计算,r意味着存在竞争条件的速率:
线程数量=2
n=2, m=2 r=0.5
n=2, m=3 r=0.333333
n=2, m=4 r=0.25
n=2, m=5 r=0.2
n=2, m=6 r=0.166667
n=2, m=7 r=0.142857
n=2, m=8 r=0.125
n=2, m=9 r=0.111111
n=2, m=10 r=0.1
n=2, m=11 r=0.0909091
...
n=2, m=100 r=0.01
...
线程数量=3
n=3, m=3 r=0.777778
n=3, m=4 r=0.625
n=3, m=5 r=0.52
n=3, m=6 r=0.444444
n=3, m=7 r=0.387755
...
n=3, m=29 r=0.10107
...
线程数量=5
n=5, m=5 r=0.9616
n=5, m=6 r=0.907407
n=5, m=7 r=0.850062
n=5, m=8 r=0.794922
n=5, m=9 r=0.743941
...
n=5, m=96 r=0.100425
线程数量=8
n=8, m=8 r=0.997597
n=8, m=9 r=0.99157
n=8, m=10 r=0.981856
n=8, m=11 r=0.968964
n=8, m=12 r=0.953583
...
n=8, m=268 r=0.100095
优点是选择一个合适的m,我们可以在90%的时间内获得无锁定
缺点是我们浪费了很多资源。
我的想法对吗?有更好的解决方案吗?
我认为您的算法的复杂性不值得它带来好处。实际上,还有许多更简单的解决方案。在开始之前,最好确定一下使用模式。我可以这样总结:
- HashTable只读-初始化一次,读取是安全的
- 仅追加或读/写比率高-每次写入都重新创建哈希表,并使用Interlocked.CompreExchange进行替换
- 读/写比率低-使用基于spinwait的读/写锁
请记住,确定问题最佳解决方案的唯一方法是仔细测试和测量!