#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <vector>
#include <string>
#include <iostream>
FILE* fp;
pthread_mutex_t demoMutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t conditionVariable = PTHREAD_COND_INITIALIZER;
unsigned int condition = 0;
struct serverInfo
{
unsigned int serverId;
pthread_t threadId;
std::vector<std::string> queue;
};
std::vector<serverInfo> serverInfoVector;
void* printHello(void* threadId)
{
pthread_t* my_tid = (pthread_t*)threadId;
pthread_mutex_lock(&demoMutex);
while (condition == 0)
pthread_cond_wait(&conditionVariable, &demoMutex);
unsigned int i = 0;
char found = false;
if (serverInfoVector.size () > 0) {
while ((i <= serverInfoVector.size()) && (found == false)) {
if (*my_tid == serverInfoVector[i].threadId) {
found = true;
break;
}
else
i++;
}
}
while (!serverInfoVector[i].queue.empty()) {
std::cout << "\nThread: " << pthread_self() << ", poped from queue: " << serverInfoVector[i].queue.front();
serverInfoVector[i].queue.pop_back();
}
pthread_mutex_unlock(&demoMutex);
pthread_exit(NULL);
}
void checkServerExists(unsigned int serverNumber, std::string message)
{
unsigned int i = 0;
char found = false;
pthread_mutex_lock(&demoMutex);
if (serverInfoVector.size () > 0) {
while ((i <= serverInfoVector.size()) && (found == false)) {
if (serverNumber == serverInfoVector[i].serverId) {
found = true;
break;
}
else
i++;
}
}
if (found == false) {
// This server doesn't exist, so create a thread for it, create a queue for it, push the message in the corresponding queue.
// Push the server number in the serverNumberArray.
// Create a thread for it.
pthread_t newThread;
int returnValue;
if ((returnValue = pthread_create (&newThread, NULL, printHello, (void*) &newThread)) != 0) {
printf("\nerror: pthread_create failed with error number %d", returnValue);
}
printf("\nIn checkServerExists()`: thread id %ld\n", newThread);
// Push the message in its queue.
serverInfo obj;
obj.serverId = serverNumber;
obj.threadId = newThread;
obj.queue.push_back(message);
serverInfoVector.push_back(obj);
condition++;
pthread_cond_signal(&conditionVariable);
pthread_mutex_unlock(&demoMutex);
for (unsigned int i = 0; i < serverInfoVector.size(); i++)
pthread_join(serverInfoVector[i].threadId, NULL);
}
else {
// This server exists, so lookup its thread and queue, push the message in the corresponding queue.
printf("\nIn else ()`: thread id %ld\n", serverInfoVector[i].threadId);
serverInfoVector[i].queue.push_back(message);
condition++;
pthread_cond_signal(&conditionVariable);
pthread_mutex_unlock(&demoMutex);
for (unsigned int i = 0; i < serverInfoVector.size(); i++)
pthread_join(serverInfoVector[i].threadId, NULL);
}
}
int main()
{
fp = fopen("xyz", "w");
checkServerExists(1, "anisha");
checkServerExists(2, "kaul");
checkServerExists(1, "sanjeev");
checkServerExists(2, "sharma");
}
输出:
In checkServerExists ()`: thread id 140233482061584
Thread: 140233482061584, poped from queue: anisha
In checkServerExists ()`: thread id 140233482061584
In else ()`: thread id 140233482061584
In else ()`: thread id 140233482061584
问题是似乎只创建了一个线程!我在main()中调用了函数checkServerExists
4次,在不同的serverID中调用了2次,因此应该创建两个线程吗?
我错过了什么?
答案 0 :(得分:2)
编辑:真正的问题是线程终止并加入为 正如hmjd所指出的那样。我要离开这个, 而不是删除它,因为以下也是问题。
我在您发布的输出中看到两个新线程的创建:"In
checkServerExists"
仅在您创建新线程时输出。我也
请参阅printf
中的未定义行为:newThread
具有类型
pthread_t
,可以是系统想要的任何东西,而且是
可能是long
以外的其他东西,这是所需要的
您传递给printf
的格式。据我所知,没有办法
(可移植地)输出pthread_t
(除了它的十六进制转储)
字节);您显示为线程ID的值并不意味着什么。
另外,您无法比较pthread_t
使用==
,您需要使用
pthread_equal
。 (至少在我使用的一个平台上,pthread_t
是一个
struct
。)
您的代码还有许多其他奇怪的事情。为什么要申报
例如,found
类型为char
,而不是类型bool
。为什么呢
found == false
,而不是!found
。为什么break;
在
循环,因为你在循环控制变量中有条件。很多
更checkServerExists
开头的惯用形式将是:
for ( std::vector<ServerInfo>::iterator current = serverInfoVector.begin();
current != serverInfoVector.end() && current->serverId != serverNumber;
++ current ) {
}
if ( current == serverInfoVector.end() ) {
// not found...
} else {
// found...
}
假设您没有为查找创建谓词对象,只是
使用std::find
。
答案 1 :(得分:1)
我不确定这是否有助于此行为,但以下是错误:
while ((i <= serverInfoVector.size ()) && (found == false))
{
if (serverNumber == serverInfoVector [i].serverId)
{
found = true;
break;
}
else
i++;
}
由于serverInfoVector[i]
中的<=
条件, if
将访问太多。改为:
while ((i < serverInfoVector.size ()) && (found == false))
编辑:
我认为这就是问题:当调用checkServerExists()
时,似乎等待它开始完成的线程:
for (unsigned int i = 0; i < serverInfoVector.size(); i++)
pthread_join(serverInfoVector[i].threadId, NULL);
这意味着线程标识140233482061584
不再使用,并且可以再次与新线程关联。当下一次调用checkServerExists()
时,重新使用线程ID,给人的印象是只启动了一个线程。
编辑2:
正如施瓦茨所指出的,这是不正确的:
if (*my_tid == serverInfoVector[i].threadId) {
您需要使用pthread_equal()
来比较两个pthread_t
。改为:
if (pthread_equal(*my_tid, serverInfoVector[i].threadId)) {
或者将serverId
作为参数传递给线程。
答案 2 :(得分:1)
if (*my_tid == serverInfoVector[i].threadId) {
你不能用这种方式比较pthread_t
。这是一个C接口,而不是C ++接口。因此没有操作员超载来使这种比较合理地工作。出于同样的原因这是错误的:
const char *foo="foo";
if(foo == "foo") ...
你必须使用合理的比较功能。在我的示例中,strcmp
。在您的代码中pthread_equal。
此外,在您pthread_join
一个帖子后,其pthread_t
不再有效。您不能再将其传递给任何pthread_*
函数。这与将指针传递给free
后取消引用一样糟糕。
(您可能需要修复此主题中报告的所有错误,并使用您更新的代码发布新问题,并说明您仍然遇到的任何问题。)
答案 3 :(得分:0)
我可以理解为什么它没能像你期望的那样工作。你的服务器端使用从main传入的唯一标识符来确定它的线程id应该是什么,但是线程函数本身使用的是线程id。
您创建的第一个工作线程已终止,第二个工作线程的ID与第一个相同,因为此ID现已可用。
主线程将字符串放在向量中第二个元素的队列中,但是你的线程正在拾取向量的第一个元素,因为它有一个匹配的线程id。
顺便提一下,他们以前的海报所说的所有东西也应该被考虑。只是因为它不是产生你行为的那些。
void* printHello(void* serverptr)
{
serverInfo * info = static_cast< serverInfo * >(serverptr);
// look through the queue
}
将集合类型更改为std::list
或std::deque
,这样如果您在线程处理它时随后执行了push_back,它将不会使指针无效。
在checkServerExists
中,将serverInfo的地址传递给线程函数而不是thread_id的地址。
你也可以&#34;索引&#34;您的集合使用从int到serverInfo *的映射,或者如果使用列表,则使用列表迭代器。您不应该使用std::map<int, serverInfo>
,因为如果您向地图添加新条目,它可能会使您的指针无效。
顺便提一下,你的工作线程看起来太早终止,因为当你将后来的信息发送到旧的ID时,线程已经消失了。
队列为空不应该是终止线程的条件,你应该使用其他方法。
顺便提一下,虽然它是线程安全的,但你的互斥锁被锁定了很长时间,以至于你不会通过在这里使用多个线程来实现任何不错的性能。