Aqu*_*irl 1 c++ multithreading pthreads
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 %ld\n", 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 %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.
***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;
}
Run Code Online (Sandbox Code Playgroud)
这段代码得到了改进,问题仍然存在(程序挂起,第二个线程没有显示出来).
checkServerExistsfunction(在当前情况下)导致创建新线程并将其存储在数组中newThread.
checkServerExists 函数启动一个新线程,
线程创建后,它将立即调用其函数printHello并在条件变量上被阻塞.
checkServerExists 函数然后输入全局结构队列中的值,设置唤醒线程的信号.
现在,我错过了什么?
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 %ld\n", 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 %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.
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;
}
Run Code Online (Sandbox Code Playgroud)
在这个编辑中,我把锁放在checkServerExists函数的顶部(这个函数处理全局结构serverInfoVector)
还挂着.:卫生署:
这段代码坏了.
首先,您在checkServerExists不锁定互斥锁的情况下修改内部变量.这是未定义的行为.
如果你解决了这个问题,那么你也没有在printHello函数外发出你的条件变量的信号.因此,一旦线程在pthread_cond_wait调用中被阻塞,它将仅由于虚假唤醒而被唤醒,并且当另一个printHello线程发出信号时它将被唤醒.您应该pthread_cond_signal在设置condition标志的位置调用,而不是在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 %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;
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
646 次 |
| 最近记录: |