2014-12-05 200 views
1

这个问题可能很简单,但我仍然无法找出一个有效的方法来做到这一点。我有以下设置:高效的多线程共享访问内存缓冲区

1)线程A不断地从互联网下载数据到内存缓冲区。

2)同时,线程B想要读取已经从这个缓冲区下载的数据。

缓冲区不是圆形或任何东西。有一个写入游标和一个读取游标。一旦线程A向缓冲区写入了一些内容,它就会更新写入光标,告诉线程B当前有多少数据可用于读取。

问题是线程B经常读取数千字节,但一次只读取一个字节的步骤。因此,我需要一种有效的方式来同步两个线程。我已经尝试了SetEvent()和WaitForSingleObject(),但是这看起来很慢(或者我做了错误),因为线程B正在从缓冲区读取1个字节的数据包,所以线程B必须为每个字节调用WaitForSingleObject需要阅读。听起来像很多开销。

不可能在没有任何互斥体(临界区)保护的情况下执行此操作吗?即线程B可以轮询写入光标,直到有足够的数据可用,然后复制它。但是随后会出现同步问题,即当线程A更新写入光标时,此更改是否立即反映在线程B中?我没有太多的多线程编程经验,其中的许多文章听起来都非常复杂,所以如果有人能够以正确的方式实现这一点,我会很高兴。

+1

尽量不要这样做。通常从网络中以比一个字节大得多的块读取数据。你真的只需要使用一个缓冲区?为什么线程A会将大块读入动态分配的缓冲区结构体/实例,排队(阻塞生产者 - 消费者队列),缓冲区指针指向线程B,并立即为下一次加载数据分配一个新缓冲区?不管你怎么做,单字节的线程间通信都是非常低效的。 – 2014-12-06 20:41:29

+0

谢谢,这就是我现在所做的:从流线程中读取16kb的数据包,并缓存这些数据包,以便从主程序快速基于字节访问。这是有效的,然后是投票的更好方法。 – Andreas 2014-12-07 09:57:24

回答

0

是的,您可以在一个线程中轮询在另一个线程中所做的更改,而无需互斥锁。这是非常快的,但是由于线程B不断轮询以检查新数据,所以CPU开销很高。

+0

但是数据是否立即同步?我远程记住,对线程A中的变量所做的更改可能不会立即提供给线程B. AFAIR同步只会每隔一段时间进行一次,或者在执行睡眠(0)或类似的事情时发生,但我可能在此处出错。 – Andreas 2014-12-05 22:42:37

+0

是的,你会立即同步。 – 2014-12-05 22:55:21

+0

取决于您的CPU ...但体面的CPU将立即同步。 – 2014-12-07 20:26:19