#c #multithreading
#c #многопоточность
Вопрос:
У меня есть член класса functionA, который создает поток для запуска другой функцииB. Функция B выполнит некоторую операцию и остановится через некоторое время (это своего рода запуск и забывание вызова функции, а количество необходимых вызовов функции и потоков будет зависеть от результата выполнения). Функция будет вызываться несколько раз. Я понял, что pthread_create будет принимать pthread_t в качестве первого параметра, и pthread_t должен быть доступен при создании потока. Таким образом, я не мог объявить его локальным, как показано ниже. Итак, где я мог бы объявить pthread_t?
void classA::functionA(int param)
{
pthread_t t; //could not declare local because functionA might return and destroy t before thread being created.
pthread_create(amp;t , NULL, functionB, param);
}
void functionB(int param)
{
}
Комментарии:
1. Даже если
t
будет уничтожен, как это повлияет на выполнениеfunctionB
?2. Иногда я получаю ошибку сегментации. Я думаю, это потому, что t уничтожается до создания потока.
Ответ №1:
Во-первых, вы можете поместить свой pthread_t
в стек: ваш functionA
подходит в этом отношении. pthread_create
сохраняет дескриптор потока напрямую, поэтому, как только он возвращает дескриптор, он становится действительным. Недавно созданный поток еще не обязательно начал выполняться, но это не имеет значения, поскольку он не коснется этого дескриптора.
Однако вам нужно как-то управлять своим потоком. Если вы явно не создаете его отдельно, то вы должны вызвать pthread_join
or pthread_detach
в своем дескрипторе. Если вы не вызываете ни то, ни другое, то происходит утечка ресурсов. Если это действительно поток «запустить и забыть», то вам следует использовать pthread_detach
для обеспечения очистки операционной системы после завершения потока.
В любом случае, вам необходимо убедиться, что объекты, к которым обращается поток, переживут любые потенциальные обращения к ним со стороны потока (например, не уничтожая их до тех пор, пока не будет установлен флаг «Мне больше не нужны эти объекты»)
Ответ №2:
У вас может быть переменная pthread_t в стеке, с этим проблем нет.
Есть ли причина, по которой вы не используете оболочку потока, такую как boost::thread? Это значительно упростило бы вашу жизнь. http://www.boost.org/doc/libs/1_45_0/doc/html/thread/thread_management.html
Другое дело, что вы не можете просто запустить поток и забыть его, потому что после того, как вы это сделаете, объект не должен быть уничтожен до того, как другой поток прекратит доступ к нему. Другими словами, деструктор вашего объекта должен убедиться, что другие потоки не обращаются к объекту.
Ответ №3:
Я не верю, что у вас проблема, поскольку pthread_create()
не вернется до того, как в него будет записан новый идентификатор потока, t
так что в этом вообще нет необходимости new pthread_t
. Вам, конечно, нужно проверить возврат из pthread_create()
.
Ответ №4:
Я бы сделал это таким образом:
class classA
{
void functionA();
static void void functionB(classA* aThis);
};
void classA::functionA(int param)
{
//create thread: note that this way pthread_t can even become the class-member
}
void classA::functionB(classA* aThis)
{
classA* theThis = static_cast<classA*>(aThis);
//now you can access classA members here easily
}