C#双线程读写float值异常:BufferData仅填充单一数值求解
问题根源
你的核心问题不是线程同步的语法错误,而是对线程执行速度的认知偏差,以及填充数组的逻辑不符合需求:
- Thread2的数组填充循环(524288次迭代)执行速度极快,远超过Thread1写入
_readWriteValue的频率。在一次数组填充过程中,Thread1大概率只能完成0次或1次写入,导致整个数组被同一个值填满。 - 另外,
_readWriteValue和_stop没有标记为volatile,可能存在CPU缓存一致性问题,导致Thread2无法及时看到Thread1的最新写入,但这不是当前现象的主要原因。
解决方案
根据你的需求(Thread1生成随机值,Thread2收集足够多的随机值后批量处理),正确的做法是用生产者-消费者模式,让Thread1生产的每个随机值都被收集,直到攒够BUFFER_SIZE个再处理。
修正后的代码示例
private const int BUFFER_SIZE = 65536 * 8; private readonly ConcurrentQueue<float> _valueQueue = new ConcurrentQueue<float>(); private volatile bool _stop = false; private void Thread1() { Random ran = new Random(); while (!_stop) { // 生产随机值并加入队列 _valueQueue.Enqueue(ran.Next(1, 100)); // 可根据需求添加适当延迟,避免队列增长过快 // Thread.Sleep(1); } } private void Thread2() { while (!_stop) { float[] bufferData = new float[BUFFER_SIZE]; int filledCount = 0; // 从队列中取足够多的值填充数组 while (filledCount < BUFFER_SIZE && !_stop) { if (_valueQueue.TryDequeue(out float value)) { bufferData[filledCount++] = value; } else { // 队列空时短暂等待,避免空转占用CPU Thread.SpinWait(10); } } if (filledCount == BUFFER_SIZE) { ProcessMethod(bufferData); } } } private void ProcessMethod(float[] data) { // 处理逻辑 }
关键调整点
- 用
ConcurrentQueue作为生产者(Thread1)和消费者(Thread2)的中间缓冲区,确保每个生成的随机值都能被收集。 - Thread2不再直接读取共享变量,而是从队列中取已生成的随机值,直到填满数组再处理。
_stop标记为volatile,确保线程间的可见性。- 添加了空队列时的等待逻辑,避免Thread2空转消耗CPU。
其他注意事项
- 如果不需要严格的实时性,可以在Thread1中添加适当延迟,控制随机值的生成速度,避免队列无限增长。
- 若要保证单个变量的线程安全访问,也可以用
Interlocked类或lock块保护读写操作,但这解决不了你当前数组全是同一个值的问题——核心是填充逻辑的设计偏差,而非同步语法错误。
内容的提问来源于stack exchange,提问作者Alireza Izadimehr
相关产品推荐
相关产品推荐

