我是线程化的新手(以及C / C ++),我正在尝试使用多个线程来访问共享变量。
总的来说,我创建了一个变量char inputarray [100];
线程1:该线程将以2字节突发从stdin读取数据,并将它们附加到inputarray。 (通过输入文件输入)
线程2:该线程将一次读取1个字节的数据,执行计算,并将其数据放入输出数组中。
线程3:该线程将以2字节突发的形式从输出数组输出数据。 (标准输出)
我尝试了输入部分并通过传递结构使其工作,但是想在不使用结构的情况下完成它,但它一直给我带来问题。
如果我可以输入,我相信我将能够使用类似的策略来完成输出。任何帮助将不胜感激。
下面是输入线程的粗略模板。
#include <stdio.h>
#include <pthread.h>
using namespace std;
void* input(void* arg) {
char reading[3];
fread(reading,1,2,stdin);
//append to char inputarray[]..???
}
int main() {
char inputarray[100];
pthread_t t1;
pthread_create(&t1, NULL, &input, &inputarray);
void *result;
pthread_join(t1,&result);
return 0;
}
答案 0 :(得分:8)
几个问题:
我认为堆栈上的数组是共享变量的非常糟糕的选择,因为它具有固定的大小,并且从第2和第3位不清楚在哪里放置新元素或从哪里读取元素。我建议改用std::vector
或std::deque
。
最初你的容器是空的。然后线程2将一些元素推送到它。
线程3正在轮询(或等待条件变量)容器,一旦找到新元素 - 打印它们
您必须使用互斥锁同步对共享变量的访问权限(请考虑pthread互斥锁,std::mutex
或boost::mutex
)。您可能还希望使用条件变量来通知线程3有关队列中的新元素。但是对于初始实施,它不是必需的。
你真的必须使用pthread原语吗?通常,使用std::thread
,std::mutex
(如果您有现代编译器)或boost::thread
,boost::mutex
则更容易和更安全(即异常安全)。
答案 1 :(得分:2)
你在正确的轨道上:
注意,pthreads库是C libs所以你需要将回调声明为C函数:
extern "C" void* input(void* arg);
我个人会传递第一个元素的地址:
pthread_create(&t1, NULL, &input, &inputarray[0]);
这使您的代码看起来像这样:
void* input(void* arg) {
try
{
char* inputarray = (char*)arg;
size_t inputLocation = 0;
// Need to make sure you don't over run the buffer etc...
while(!finished())
{
fread(&inputarray[inputLocation],1,2,stdin);
inputLocation += 2;
}
}
catch(...){} // Must not let exceptions escape a thread.
return NULL;
}
这种风格的问题在于你将协调的责任放在每个单独的线程中。编写器线程必须检查读者线程必须检查是否有可用的数据等。所有这些都需要协调,所以现在需要一些共享的互斥锁和条件变量。
更好的选择是将责任转移到沟通的对象中。因此,我将创建一个具有通信所需的基本操作的类,然后使其方法进行适当的检查。
class Buffer
{
public:
void write(......); //
void read(.....); //
private:
// All the synchronization and make sure the two threads
// behave nicely inside the object.
};
int main()
{
pthread_t threads[3];
std::pair<Buffer, Buffer> comms;
// comms.first inputToRead
// comms.second processesToOutput
pthread_create(&threads[0], NULL, &readInput, &comms.first); // Input
pthread_create(&threads[1], NULL, &procInput, &comms); // Processing
pthread_create(&threads[2], NULL, &genOutput, &comms.second); // Output
void *result;
pthread_join(threads[0],&result);
pthread_join(threads[1],&result);
pthread_join(threads[2],&result);
}
作为旁注:
除非你的数据处理有些奇怪。这可能会更快地编写为单线程应用程序。