Delphi XE10.2.3多线程大量读和少量写公共资源时,用原子自旋读写锁代替互斥锁提高效率

多线程这玩意就是这么矛盾,使用多线程的初衷是为了提高CPU等资源使用率和加快程序并发处理能力,这是大家都希望看到的,但另一方面却必须为多线程读写公共资源而绞尽脑汁,各种奇葩处理方式层出不穷,利弊自知。

     对于一个高性能服务器在处理多数读取,少量写入的场景时,如果还是使用常规的互斥锁方式,显然就不明智了,这种读多写少的场景最适合使用读写锁方式,读取时不加锁,多线程并发读取,效率是最高的,要写入数据时堵塞所有后面进来的读写线程,写完释放锁,所有读取线程又并发读取,这种思路非常简洁精妙。

    所以在对比几种锁的实现,并参考C、C++、JAVA的代码后,使用DelphiXE10.2.3 Pascal写了几个利用CPU原子操作性加自旋(自旋听上去很高深,其实就是TM的While原地转圈)(原子操作和自旋锁可百度)的方式实现读写锁的代码,这几种方式都不是本人发明和发现的,Linux核心和部分数据库底层锁处理都有采用该方式,网上的C、C++、JAVA有很多实现,就没有较好的PASCAL代码实现,网上看到几篇DELPHI的读写锁,还翻墙出来找了一遍,最后复制下来一测试,要不是锁失败造成读写脏数据和AV,要不就是并发量低时效率高,并发量一高就比互斥锁还悲剧。

    这两天设计完原子自旋锁后,与互斥锁在相同条件下进行了对比,这里提供测试程序的源代码和原子锁的DCU文件,有兴趣参与测试的可自行修改测试条件,并判断原子锁是否存在读写脏数据问题,并在群中公布出来,即可获得原子锁源代码。连测试都不愿意参与就索要源代码的,就不要进群了。

    下图为测试对比图,原子锁写和线程锁写都只间断执行了100次(总共1000次,每隔10次一个写线程),两个方式的读线程分别执行了900次,可以看到,线程锁随着线程的增多,读写延迟都越来越高,而原子锁只有写时有一些等待,读时基本不受影响,效率非常高。注:纵轴是毫秒时间,横轴是执行次数


测试注意:

1、原子读写锁不能嵌套使用,BeginWrite和EndWrite成对使用,BeginRead和EndRead成对使用,不能混用,也不能嵌套使用。

2、原子锁的DCU文件分别在WIN32和WIN64目录中,注意引用位置

3、与所有锁一样,多线程读取出的指针、对象等地址操作类的内容是不能直接修改的,除非将读出的内容放到另一个数组中(或其他方式),保证一次读取后,不会再有另外的线程能够读取到相同地址的内容,然后才能修改内容。

4、适合在多读少写的应用场景,如果读写频率基本一致,原子锁的效率基本与互斥锁一样。

测试程序下载地址:https://download.csdn.net/download/u011784006/10345193

QQ群:DELPHI开发者群:733975324

猜你喜欢

转载自blog.csdn.net/u011784006/article/details/79918438