我在使用多线程的时候,有很小的概率(大概1/1000)会出错,系统负载高时(CPU100%)出错的概率也会增大(可能到1/10),一旦出错,就会导致整个任务中断,而多线程对于我是必须品,单线程的效率是我无法接受的,所以想知道出错的原因,以及有没有什么办法可以避免或解决。
示例:
我要解散名称为1-1000的总共1000个文件夹,每个文件夹内有一个和文件夹名称相同文件,处理方式为打包的子程序,只有传入参数文件夹路径,没有传出参数。
使用多线程时,系统会报错,在名称为233的文件夹中没有找到233.xxx这个文件(实际上我确认这个文件已经被解散成功,我在上层目录找到了它,此时233文件夹就是个空文件夹,所以它才没有找到233.xxx这个文件,它早就应该被删除,而不是再次进入多线程中)。
因为多线程不支持调试,我也做了一些我自认为有效的测试,测试的结果大致意思如下:
在每个步骤中,以多线程,分发1、2、3、4、5、6、7、8、9这9个数字。
我理想中的结果是这9个数字全部分发,且都只分发一次,分发的顺序无所谓,比如分发的结果是:123789456,这是我希望的结果。
但实际上的结果可能是:1224568889。
有些数字会漏发,比如7,有些数字会多发,比如28,于是就导致了错误。
我想知道,我以上的测试及猜测是对的吗?
造成这样错误的原因是什么?还是说多线程本身就这样?
如果出现这样的错误,有没有什么办法可以在动作中解决掉这种错误以让动作继续正确的运行下去?
动作我重新写一下分享给你
这是我在日志数据里找到的不知道有没有用,这段文本经常出现
2023-08-26 21:24:27,858 [106] WARN Quicker.Domain.Actions.X.BuiltinRunners.EachStepRunner - [多线程]出错:发生一个或多个错误。已释放该信号量。
System.AggregateException: 发生一个或多个错误。 ---> System.ObjectDisposedException: 已释放该信号量。
在 System.Threading.SemaphoreSlim.CheckDispose()
在 System.Threading.SemaphoreSlim.Release(Int32 releaseCount)
在 Quicker.Domain.Actions.X.BuiltinRunners.EachStepRunner.<>c__DisplayClass45_1.L2wBYGHa3ad()
在 System.Threading.Tasks.Task.Execute()
--- 内部异常堆栈跟踪的结尾 ---
---> (内部异常 #0) System.ObjectDisposedException: 已释放该信号量。
在 System.Threading.SemaphoreSlim.CheckDispose()
在 System.Threading.SemaphoreSlim.Release(Int32 releaseCount)
在 Quicker.Domain.Actions.X.BuiltinRunners.EachStepRunner.<>c__DisplayClass45_1.L2wBYGHa3ad()
在 System.Threading.Tasks.Task.Execute()<---
https://getquicker.net/Sharedaction?code=2a2e6978-97fe-46f5-9937-08dba5d3aaf5
这就是解散文件夹,我刚刚又试了几次,很容易出错
我是4.0的固态,直连CPU,磁盘应该不是短板。
我曾经把线程启动间隔设为5000ms,但高负载依旧报错…报错概率和5ms似乎没差…真正有效避免出错还得调低线程数…
然后我今天分别尝试了8、12、16、20线程的操作,发现线程的提升与线程数量的提升完全不符合预期,处理相同的任务,分别花了1770、1580、1498、1424秒,也就是20线程相比8线程线程翻倍还多却只提升了24%…最具性价比的是12线程。
线程数调低之后确实不太容易出错,但就是看着那么多线程空在那里不工作,跟小核有难大核围观的既视感一样一样的…
感谢解答。