尽管尝试创建两个线程,但只创建一个线程
Only one thread gets created despite the attempt to create two
#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 %ldn", 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 %ldn", 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((中调用了该函数4 checkServerExists
,使用不同的serverID调用了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
.
我不确定这是否会导致行为,但以下是一个错误:
while ((i <= serverInfoVector.size ()) && (found == false))
{
if (serverNumber == serverInfoVector [i].serverId)
{
found = true;
break;
}
else
i++;
}
由于if
中的<=
条件,serverInfoVector[i]
将访问太多。更改为:
while ((i < serverInfoVector.size ()) && (found == false))
编辑:
我认为这就是问题所在:当调用checkServerExists()
时,它似乎在等待它开始完成的线程:
for (unsigned int i = 0; i < serverInfoVector.size(); i++)
pthread_join(serverInfoVector[i].threadId, NULL);
这意味着线程 ID 140233482061584
不再使用,并且可以再次与新线程关联。下次调用checkServerExists()
时,将重用线程 id,给人的印象是只启动了一个线程。
编辑2:
正如施瓦茨所指出的,这是不正确的:
if (*my_tid == serverInfoVector[i].threadId) {
您需要使用pthread_equal()
来比较两个pthread_t
。更改为:
if (pthread_equal(*my_tid, serverInfoVector[i].threadId)) {
或者将serverId
作为参数传递给线程。
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
后取消引用指针一样糟糕。
(您可能希望修复此线程中报告的一些所有错误,并发布一个新问题,其中包含更新的代码以及您仍然存在的任何问题的描述。
我明白为什么它无法按您的期望工作。您的服务器端正在使用从 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的地址。
您还可以使用从 int 到 serverInfo* 或列表迭代器的映射(如果使用列表(来"索引"集合。但是,不应使用std::map<int, serverInfo>
因为如果向地图添加新条目,指针可能会失效。
顺便说一下,您的工作线程似乎过早终止,因为当您将后面的信息发送到旧 id 时,线程已经消失了。
队列为空不应是终止线程的条件,您应该使用其他方法。
顺便说一下,虽然它是线程安全的,但您的互斥锁被锁定了很长时间,以至于您在这里使用多个线程并不能真正实现任何体面的性能。
- 两个线程一个使用流 Api,另一个线程创建文件失败并出现错误ERROR_SHARING_VIOLATION
- C++ 线程创建/删除与线程停止/恢复
- Qt - 如何从线程创建 QFuture
- 我可以使用Qt线程ID为每个线程创建唯一的缓存吗?
- 零MQ 后台线程创建
- OpenMP 线程创建
- GLFW & ImGui:从 main 以外的线程创建 ImGui 控件
- 对象:无法为位于不同线程中的父线程创建子级
- C++ 11:线程创建给我一个"Attempt to use a deleted function"错误
- C 的周期性线程创建
- MPI - 当数组初始化值必须为常量时,如何为工作线程创建部分数组
- 当主GUI线程被阻塞时,如何从工作线程创建无模式对话框
- 多个线程创建5个线程来计算质数
- 为线程创建模板
- 线程创建,CRT和DLL是如何完成的?
- 同步线程创建和销毁(静态)对象
- 竞争条件:一个线程创建静态对象,另一个线程在初始化完成之前使用它.如何处理
- 从不同线程创建QMainWindow
- QFuture 无法为位于不同线程中的父线程创建子级
- ( QNativeSocketEngine)QObject:无法为位于不同线程中的父线程创建子级