C++ 如何设置pthread_cond_signal使程序不';不挂? 编辑1:
在这次编辑中,我将锁放在C++ 如何设置pthread_cond_signal使程序不';不挂? 编辑1:,c++,multithreading,pthreads,C++,Multithreading,Pthreads,在这次编辑中,我将锁放在checkServerExists函数的顶部(该函数处理全局结构serverInfoVector) 仍然挂着doh:我猜第二个线程没有从等待中唤醒。第一个线程试图向条件变量发送信号,但秒数还没有开始。我想知道为什么它在第一个线程中甚至超过了等待,但它可能永远不会等待,因为线程在条件已经为1之后开始执行。我猜第二个线程没有从等待中醒来。第一个线程试图向条件变量发送信号,但秒数还没有开始。我想知道为什么它甚至超过了第一个线程中的等待,但它可能永远不会等待,因为该线程在条件已经
checkServerExists
函数的顶部(该函数处理全局结构serverInfoVector
)
仍然挂着doh:我猜第二个线程没有从等待中唤醒。第一个线程试图向条件变量发送信号,但秒数还没有开始。我想知道为什么它在第一个线程中甚至超过了等待,但它可能永远不会等待,因为线程在条件已经为1之后开始执行。我猜第二个线程没有从等待中醒来。第一个线程试图向条件变量发送信号,但秒数还没有开始。我想知道为什么它甚至超过了第一个线程中的等待,但它可能永远不会等待,因为该线程在条件已经为1之后开始执行。此代码已被破坏 首先,您正在修改
checkServerExists
中的变量,而不锁定互斥锁。这是未定义的行为
如果您解决了这个问题,那么您也不会在printHello
函数之外发送条件变量的信号。因此,一旦线程在pthread\u cond\u wait
调用中被阻塞,它只会由于虚假唤醒而被唤醒,并且当另一个printHello
线程发出信号时才会被唤醒。您应该在设置条件
标志的位置调用pthread\u cond\u signal
,而不是在printHello
中
条件变量只是一种通知机制。您需要将谓词与之关联,这是正在等待的条件(在您的示例中,condition!=0
)。您必须确保设置和测试条件时访问的变量受到互斥锁的保护,并且该互斥锁是传递给pthread\u cond\u wait
的互斥锁,以避免潜在的争用条件。当设置变量以指示休眠线程应该唤醒时,则调用pthread\u cond\u signal
我已经稍微修改了您的代码,使其能够正常工作。特别是,我在pthread\u cond\u wait
调用周围放置了一个循环,并在调用pthread\u join
之前解锁了互斥锁,以便printHello
线程可以获取互斥锁并继续。决不能在线程连接中持有互斥锁。这段代码仍然可以大大改进——除其他外,它不是异常安全的
#include <pthread.h>
#include <stdio.h>
#include <vector>
#include <string>
FILE *fp;
pthread_mutex_t demoMutex;
pthread_cond_t demoConditionVar;
unsigned short globalThreadIndex = 0;
struct serverInfo
{
unsigned int serverId;
pthread_t threadId;
std :: vector <pthread_t> queue;
};
std :: vector <serverInfo> serverInfoVector;
void * printHello (void* threadId)
{
pthread_t *my_tid = (pthread_t *)threadId;
printf ("\nIn `printHello ()`: thread id %ld\n", pthread_self ());
pthread_mutex_lock (&demoMutex);
unsigned int i = 0;
bool found = false;
while (serverInfoVector.empty())
pthread_cond_wait (&demoConditionVar, &demoMutex);
while ((i < serverInfoVector.size ()) && !found)
{
if (*my_tid == serverInfoVector [i].threadId)
{
found = true;
break;
}
else
i++;
}
if (found)
{
pthread_t writeToFile = pthread_self ();
unsigned short iterate;
for (iterate = 0; iterate < 10000; iterate++)
{
fprintf (fp, " %d %d", iterate, 4);
fprintf (fp, " %lu %lu", writeToFile, sizeof (pthread_t));
if (!serverInfoVector [i].queue.empty ())
{
fprintf (fp, " %c %u", 'A', 1);
fprintf (fp, " %lu %lu", serverInfoVector [i].queue.front (), sizeof (pthread_t));
serverInfoVector [i].queue.pop_back ();
}
fprintf (fp, "\n %lu %u", writeToFile, 1);
}
}
pthread_mutex_unlock (&demoMutex);
pthread_exit (NULL);
}
void checkServerExists (unsigned int serverNumber, std :: string message)
{
unsigned int i = 0;
bool found = false;
pthread_mutex_lock (&demoMutex);
if (serverInfoVector.size () > 0)
{
while ((i <= serverInfoVector.size ()) && (found == false))
{
if (serverNumber == serverInfoVector [i].threadId)
{
found = true;
break;
}
else
i++;
}
}
if (!found)
{
pthread_t newThread [2];
int returnValue;
if ((returnValue = pthread_create (&newThread [globalThreadIndex], NULL, printHello, (void*) &newThread [globalThreadIndex])) != 0)
{
printf ("\nerror: pthread_create failed with error number %d", returnValue);
}
printf ("\nIn checkServerExists ()`: thread id %ld\n", newThread [globalThreadIndex]);
serverInfo obj;
obj.serverId = serverNumber;
obj.threadId = newThread [globalThreadIndex];
obj.queue.push_back (newThread [globalThreadIndex]);
serverInfoVector.push_back (obj);
// Now, since something has been pushed in the vector, it makes sense to wake up the sleeping thread.
// Now, since something has been pushed in the vector, it makes sense to wake up the sleeping thread.
pthread_cond_signal (&demoConditionVar);
pthread_mutex_unlock(&demoMutex);
pthread_join (newThread [globalThreadIndex], NULL);
}
else
{
pthread_mutex_unlock(&demoMutex);
}
}
int main ()
{
fp = fopen ("xyz", "w");
pthread_mutex_init (&demoMutex, NULL);
pthread_cond_init (&demoConditionVar, NULL);
checkServerExists (1, "anisha");
globalThreadIndex++;
checkServerExists (2, "anisha");
return 0;
}
#包括
#包括
#包括
#包括
文件*fp;
pthread_mutex_t demoMutex;
pthread_cond_t demoConditionVar;
无符号短globalThreadIndex=0;
结构服务器信息
{
无符号int-serverId;
pthread_t threadId;
向量队列;
};
向量服务器信息向量;
void*printHello(void*threadId)
{
pthread_t*my_tid=(pthread_t*)threadId;
printf(“\n`printHello()`:线程id%ld\n”,pthread_self());
pthread_mutex_lock(&demoMutex);
无符号整数i=0;
bool-found=false;
while(serverInfoVector.empty())
pthread_cond_wait(&demoConditionVar,&demoMutex);
而((i0)
{
而((i此代码被破坏
首先,您正在修改checkServerExists
中的变量,而不锁定互斥锁。这是未定义的行为
如果您解决了这个问题,那么您也不会在printHello
函数外发送条件变量的信号。因此,一旦线程在pthread_cond_wait
调用中被阻塞,它将只会由于虚假唤醒而唤醒,并且当另一个printHello
线程发出信号时。您应该调用pthread_cond_\u sign在设置条件
标志的位置,而不是在printHello
中设置al
条件变量只是一种通知机制。您需要将谓词与之关联,这是等待的条件(在您的情况下,condition!=0
)。您必须确保设置和测试条件时访问的变量受互斥锁保护,并且此互斥锁是传递给pthread\u cond\u wait
的互斥锁,以避免潜在的争用条件。当您将变量设置为指示休眠线程应唤醒时,则调用pthread\u cond\u signal
我稍微修改了您的代码以使其正常工作。特别是,我在pthread\u cond\u wait
调用中加入了循环,并在调用pthread\u join
之前解锁了互斥锁,以便printHello
线程可以获取互斥锁并继续。您不应该在线程连接中持有互斥锁。此代码可能直到有了很大的改进——除其他外,它也不例外安全
#include <pthread.h>
#include <stdio.h>
#include <vector>
#include <string>
FILE *fp;
pthread_mutex_t demoMutex;
pthread_cond_t demoConditionVar;
unsigned short globalThreadIndex = 0;
struct serverInfo
{
unsigned int serverId;
pthread_t threadId;
std :: vector <pthread_t> queue;
};
std :: vector <serverInfo> serverInfoVector;
void * printHello (void* threadId)
{
pthread_t *my_tid = (pthread_t *)threadId;
printf ("\nIn `printHello ()`: thread id %ld\n", pthread_self ());
pthread_mutex_lock (&demoMutex);
unsigned int i = 0;
bool found = false;
while (serverInfoVector.empty())
pthread_cond_wait (&demoConditionVar, &demoMutex);
while ((i < serverInfoVector.size ()) && !found)
{
if (*my_tid == serverInfoVector [i].threadId)
{
found = true;
break;
}
else
i++;
}
if (found)
{
pthread_t writeToFile = pthread_self ();
unsigned short iterate;
for (iterate = 0; iterate < 10000; iterate++)
{
fprintf (fp, " %d %d", iterate, 4);
fprintf (fp, " %lu %lu", writeToFile, sizeof (pthread_t));
if (!serverInfoVector [i].queue.empty ())
{
fprintf (fp, " %c %u", 'A', 1);
fprintf (fp, " %lu %lu", serverInfoVector [i].queue.front (), sizeof (pthread_t));
serverInfoVector [i].queue.pop_back ();
}
fprintf (fp, "\n %lu %u", writeToFile, 1);
}
}
pthread_mutex_unlock (&demoMutex);
pthread_exit (NULL);
}
void checkServerExists (unsigned int serverNumber, std :: string message)
{
unsigned int i = 0;
bool found = false;
pthread_mutex_lock (&demoMutex);
if (serverInfoVector.size () > 0)
{
while ((i <= serverInfoVector.size ()) && (found == false))
{
if (serverNumber == serverInfoVector [i].threadId)
{
found = true;
break;
}
else
i++;
}
}
if (!found)
{
pthread_t newThread [2];
int returnValue;
if ((returnValue = pthread_create (&newThread [globalThreadIndex], NULL, printHello, (void*) &newThread [globalThreadIndex])) != 0)
{
printf ("\nerror: pthread_create failed with error number %d", returnValue);
}
printf ("\nIn checkServerExists ()`: thread id %ld\n", newThread [globalThreadIndex]);
serverInfo obj;
obj.serverId = serverNumber;
obj.threadId = newThread [globalThreadIndex];
obj.queue.push_back (newThread [globalThreadIndex]);
serverInfoVector.push_back (obj);
// Now, since something has been pushed in the vector, it makes sense to wake up the sleeping thread.
// Now, since something has been pushed in the vector, it makes sense to wake up the sleeping thread.
pthread_cond_signal (&demoConditionVar);
pthread_mutex_unlock(&demoMutex);
pthread_join (newThread [globalThreadIndex], NULL);
}
else
{
pthread_mutex_unlock(&demoMutex);
}
}
int main ()
{
fp = fopen ("xyz", "w");
pthread_mutex_init (&demoMutex, NULL);
pthread_cond_init (&demoConditionVar, NULL);
checkServerExists (1, "anisha");
globalThreadIndex++;
checkServerExists (2, "anisha");
return 0;
}
#include <pthread.h>
#include <stdio.h>
#include <vector>
#include <string>
FILE *fp;
pthread_mutex_t demoMutex;
pthread_cond_t demoConditionVar;
unsigned short globalThreadIndex = 0;
struct serverInfo
{
unsigned int serverId;
pthread_t threadId;
std :: vector <pthread_t> queue;
};
std :: vector <serverInfo> serverInfoVector;
void * printHello (void* threadId)
{
pthread_t *my_tid = (pthread_t *)threadId;
printf ("\nIn `printHello ()`: thread id %ld\n", pthread_self ());
pthread_mutex_lock (&demoMutex);
unsigned int i = 0;
bool found = false;
while (serverInfoVector.empty())
pthread_cond_wait (&demoConditionVar, &demoMutex);
while ((i < serverInfoVector.size ()) && !found)
{
if (*my_tid == serverInfoVector [i].threadId)
{
found = true;
break;
}
else
i++;
}
if (found)
{
pthread_t writeToFile = pthread_self ();
unsigned short iterate;
for (iterate = 0; iterate < 10000; iterate++)
{
fprintf (fp, " %d %d", iterate, 4);
fprintf (fp, " %lu %lu", writeToFile, sizeof (pthread_t));
if (!serverInfoVector [i].queue.empty ())
{
fprintf (fp, " %c %u", 'A', 1);
fprintf (fp, " %lu %lu", serverInfoVector [i].queue.front (), sizeof (pthread_t));
serverInfoVector [i].queue.pop_back ();
}
fprintf (fp, "\n %lu %u", writeToFile, 1);
}
}
pthread_mutex_unlock (&demoMutex);
pthread_exit (NULL);
}
void checkServerExists (unsigned int serverNumber, std :: string message)
{
unsigned int i = 0;
bool found = false;
pthread_mutex_lock (&demoMutex);
if (serverInfoVector.size () > 0)
{
while ((i <= serverInfoVector.size ()) && (found == false))
{
if (serverNumber == serverInfoVector [i].threadId)
{
found = true;
break;
}
else
i++;
}
}
if (!found)
{
pthread_t newThread [2];
int returnValue;
if ((returnValue = pthread_create (&newThread [globalThreadIndex], NULL, printHello, (void*) &newThread [globalThreadIndex])) != 0)
{
printf ("\nerror: pthread_create failed with error number %d", returnValue);
}
printf ("\nIn checkServerExists ()`: thread id %ld\n", newThread [globalThreadIndex]);
serverInfo obj;
obj.serverId = serverNumber;
obj.threadId = newThread [globalThreadIndex];
obj.queue.push_back (newThread [globalThreadIndex]);
serverInfoVector.push_back (obj);
// Now, since something has been pushed in the vector, it makes sense to wake up the sleeping thread.
// Now, since something has been pushed in the vector, it makes sense to wake up the sleeping thread.
pthread_cond_signal (&demoConditionVar);
pthread_mutex_unlock(&demoMutex);
pthread_join (newThread [globalThreadIndex], NULL);
}
else
{
pthread_mutex_unlock(&demoMutex);
}
}
int main ()
{
fp = fopen ("xyz", "w");
pthread_mutex_init (&demoMutex, NULL);
pthread_cond_init (&demoConditionVar, NULL);
checkServerExists (1, "anisha");
globalThreadIndex++;
checkServerExists (2, "anisha");
return 0;
}