如何设置pthread_cond_signal以使程序不会挂起?
How to set pthread_cond_signal so that the program doesn't hang?
编辑1:
FILE *fp;
pthread_mutex_t demoMutex;
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 %ldn", pthread_self ());
***pthread_mutex_lock (&demoMutex);***
unsigned int i = 0;
char found = false;
if (serverInfoVector.size () > 0)
{
// The following code should be executed when and only when the vector isn't empty.
***pthread_cond_wait (&demoConditionVar, &demoMutex);***
while ((i <= serverInfoVector.size ()) && (found == false))
{
if (*my_tid == serverInfoVector [i].threadId)
{
found = true;
break;
}
else
i++;
}
if (found == true)
{
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;
char found = false;
if (serverInfoVector.size () > 0)
{
while ((i <= serverInfoVector.size ()) && (found == false))
{
if (serverNumber == serverInfoVector [i].threadId)
{
found = true;
break;
}
else
i++;
}
}
if (found == false)
{
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 %ldn", 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.
***pthread_mutex_lock (&demoMutex)***;
// Now, since something has been pushed in the vector, it makes sense to wake up the sleeping thread.
if (serverInfoVector.size () > 0)
***pthread_cond_signal (&demoConditionVar);***
***pthread_mutex_unlock(&demoMutex);***
pthread_join (newThread [globalThreadIndex], NULL);
}
else
{
}
}
int main ()
{
fp = fopen ("xyz", "w");
***pthread_mutex_init (&demoMutex, NULL);
pthread_cond_t demoConditionVar = PTHREAD_COND_INITIALIZER;***
checkServerExists (1, "anisha");
globalThreadIndex++;
checkServerExists (2, "anisha");
return 0;
}
这段代码得到了改进,问题仍然存在(程序挂起,第二个线程没有显示)。
checkServerExists
函数(在当前情况下)导致创建新线程,并将其存储在数组newThread
中。
checkServerExists
函数启动一个新线程
当线程被创建时,它将立即调用其函数printHello
,并在条件变量上被阻塞。
checkServerExists
函数然后在全局结构的队列中输入值,设置线程唤醒的信号。
现在,我错过了什么
编辑2:
FILE *fp;
pthread_mutex_t demoMutex;
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 %ldn", pthread_self ());
***pthread_mutex_lock (&demoMutex);***
unsigned int i = 0;
char found = false;
if (serverInfoVector.size () > 0)
{
// The following code should be executed when and only when the vector isn't empty.
***pthread_cond_wait (&demoConditionVar, &demoMutex);***
while ((i <= serverInfoVector.size ()) && (found == false))
{
if (*my_tid == serverInfoVector [i].threadId)
{
found = true;
break;
}
else
i++;
}
if (found == true)
{
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;
char 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 == false)
{
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 %ldn", 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.
if (serverInfoVector.size () > 0)
***pthread_cond_signal (&demoConditionVar);***
pthread_join (newThread [globalThreadIndex], NULL);
}
else
{
}
***pthread_mutex_unlock(&demoMutex);***
}
int main ()
{
fp = fopen ("xyz", "w");
***pthread_mutex_init (&demoMutex, NULL);
pthread_cond_t demoConditionVar = PTHREAD_COND_INITIALIZER;***
checkServerExists (1, "anisha");
globalThreadIndex++;
checkServerExists (2, "anisha");
return 0;
}
在这次编辑中,我把锁放在了checkServerExists
函数的顶部(这个函数处理全局结构serverInfoVector
)
仍然悬着doh:
此代码已损坏。
首先,在不锁定互斥锁的情况下修改checkServerExists
中的变量。这是未定义的行为。
如果您修复了这个问题,那么您也不会在printHello
函数之外发出条件变量的信号。因此,一旦线程在pthread_cond_wait
调用中被阻塞,它只会由于虚假唤醒而唤醒,并且当另一个printHello
线程发出信号时。您应该在设置condition
标志时调用pthread_cond_signal
,而不是在printHello
中。
条件变量只是一种通知机制。您需要将一个谓词与之关联,这就是等待的条件(在您的情况下,为condition!=0
)。您必须确保在设置和测试条件时访问的变量受到互斥锁的保护,并且该互斥锁是传递给pthread_cond_wait
的互斥锁,以避免潜在的竞争条件。当您将变量设置为指示睡眠线程应该唤醒时,则调用pthread_cond_signal
。
我稍微修改了您的代码,使其能够工作。特别是,我已经在pthread_cond_wait
调用周围放置了循环,并在调用pthread_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 %ldn", 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 %ldn", 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;
}
我猜第二个线程没有从等待中唤醒。第一个线程试图用信号通知条件变量,但秒还没有开始。我想知道为什么它甚至在第一个线程中超过了等待,但它可能永远不会等待,因为线程在条件已经为1之后开始执行。
- 设置变量时C++程序挂起
- 第一次尝试使用new动态创建结构数组,程序挂起没有错误
- 有时ShowWindow从不调用OnShowWindow,主应用程序挂起
- 访问类成员的成员变量时 cpp 程序挂起
- 为什么线程分离时程序挂起
- 多线程程序挂起条件等待
- 调试Win32应用程序挂起
- 为什么我的多线程应用程序挂起
- 调用 Fortran 函数会使程序挂起
- 使用应用程序验证程序调试时应用程序挂起
- C++文件 I/O - 程序挂起
- MFC应用程序挂起在发出终止信号的线程中
- cvCaptureFromCAM导致程序挂起
- 在QImage上渲染QWebElement时,QT应用程序挂起
- 分段错误会导致程序挂起吗
- C++程序挂起在Visual Studio v.6中
- 通过析构函数删除动态成员会导致程序挂起
- 找出应用程序挂起的位置
- Qt程序挂起(不响应),直到函数结束,然后再次开始工作
- 使用boost::process调用外部程序会导致调用程序挂起(Linux)