多线程调用同一方法生成字符串时结果行数不符的问题咨询
多线程字符串拼接丢失数据的问题分析与解决
嘿,我来帮你捋清楚这个问题——你遇到的行数严重不足的情况,根源在于字符串的不可变性和多线程下的非原子操作,咱们一步步拆解:
为什么会丢数据?
首先,C#里的string是不可变类型,每次执行result += ...的时候,根本不是在原字符串上追加内容,而是创建了一个全新的字符串对象,再把result指向这个新对象。
而你写的result += A() + Environment.NewLine这个操作,本质上是三步:
- 读取当前
result的旧值 - 用旧值拼接新内容,生成新字符串
- 把新字符串赋值回
result
在多线程场景下,多个线程会同时执行这三步,就会出现「竞态条件」:比如线程A刚读完旧的result,还没完成拼接赋值,线程B也读到了同一个旧值,最后两个线程的拼接结果都会基于同一个旧值,导致其中一个线程的拼接结果直接被覆盖。这种情况发生成千上万次,最终结果自然只剩预期的十分之一。
而且你手动创建多个线程的方式,也没有做任何线程同步,完全是裸奔式的并发写入,数据丢失几乎是必然的。
解决方案(推荐几种实用方式)
方式1:用线程安全集合存内容,最后合并(性能最优)
先把每一行内容存入线程安全的集合,等所有线程跑完再一次性合并成字符串,避免频繁的并发写入冲突:
// 用ConcurrentBag存储每行,它是专门为多线程设计的安全集合 ConcurrentBag<string> lineCollection = new ConcurrentBag<string>(); private void Testing() { var threads = new List<Thread>(); // 这里按10万行分配任务,比如每个线程跑4次,25000个线程(也可以每个线程跑更多次减少线程数) for (int i = 0; i < 25000; i++) { threads.Add(new Thread(() => { for (int j = 0; j < 4; j++) { lineCollection.Add(A()); } })); } // 启动所有线程 foreach (var thread in threads) thread.Start(); // 等待所有线程执行完毕 foreach (var thread in threads) thread.Join(); // 最后把所有行合并成最终字符串 string result = string.Join(Environment.NewLine, lineCollection); }
方式2:StringBuilder加锁(简单直接,但性能稍差)
如果习惯用StringBuilder,一定要配合锁来保证线程安全——普通的StringBuilder本身不是线程安全的:
StringBuilder sb = new StringBuilder(); // 定义一个专用的锁对象 object lockObj = new object(); private void Testing() { var threads = new List<Thread>(); for (int i = 0; i < 100000; i++) { threads.Add(new Thread(() => { // 每次写入前加锁,保证同一时间只有一个线程操作StringBuilder lock (lockObj) { sb.Append(A()).Append(Environment.NewLine); } })); } foreach (var thread in threads) thread.Start(); foreach (var thread in threads) thread.Join(); string result = sb.ToString(); }
方式3:用Parallel并行库(更现代的写法)
现在C#更推荐用Task并行库来处理并发,代码更简洁,还能自动管理线程池:
ConcurrentBag<string> lineCollection = new ConcurrentBag<string>(); private void Testing() { // 直接并行执行10万次任务,每次生成一行 Parallel.For(0, 100000, _ => { lineCollection.Add(A()); }); string result = string.Join(Environment.NewLine, lineCollection); }
这种写法省去了手动创建和管理线程的麻烦,效率也更高。
内容的提问来源于stack exchange,提问作者John
相关产品推荐
相关产品推荐

