1> Сначала исправьте те ошибки, которые "Paul R" допустил.затем
2> вам нужно использовать функцию pthread_join, чтобы успешно завершить оба потока.
здесь после создания обоих потоков основной процесс может быть завершен, так что в это время оба потока также получаютснова, чтобы перебраться из этого использования, используйте othread_join для обоих потоков в main ()
добавьте этот код в конец вашего main ()
pthread_join(tid1, NULL);
pthread_join(tid2, NULL);
, если вы все еще не получаетеОсновы состояния расы читайте ниже.которую я скопировал из одной справочной книги
Предположим, что ваша программа имеет ряд заданий в очереди, которые обрабатываются несколькими параллельными потоками. Очередь заданий представлена связанным списком объектов структуры заданий.
После того, как каждый поток завершает операцию, он проверяет очередь, чтобы узнать, доступно ли дополнительное задание.Если значение job_queue не равно нулю, поток удаляет заголовок связанного списка и устанавливает для job_queue следующее задание в списке.Функция потока, которая обрабатывает задания в очереди, может выглядеть как в листинге 4.10.Листинг 4.10 (job-queue1.c) Потоковая функция для обработки заданий из очереди
#include <malloc.h>
struct job {
/* Link field for linked list.
struct job* next;
*/
/* Other fields describing work to be done... */
};
/* A linked list of pending jobs.
struct job* job_queue;
*/
/* Process queued jobs until the queue is empty.
void* thread_function (void* arg)
{
while (job_queue != NULL) {
/* Get the next available job. */
struct job* next_job = job_queue;
/* Remove this job from the list. */
job_queue = job_queue->next;
/* Carry out the work. */
process_job (next_job);
/* Clean up. */
free (next_job);
}
return NULL;
}
*/
4.4
Synchronization and Critical Sections
Теперь предположим, что два потока завершают задание примерно в одно и то же время, но в очереди остается только одно задание.Первый поток проверяет, является ли job_queue нулевым;обнаружив, что это не так, поток входит в цикл и сохраняет указатель на объект задания в next_job.В этот момент в Linux происходит прерывание первого потока и планирование второго. Второй поток также проверяет задание job_queue и находит его ненулевым, а также назначает тот же указатель задания для next_job.К несчастью, теперь у нас есть два потока, выполняющих одно и то же задание.
Что еще хуже, один поток отсоединит объект задания от очереди, оставив job_queue с нулевым значением. Когда другой поток оценивает job_queue-> nextвозникает ошибка сегментации.
Это пример состояния гонки.При «счастливых» обстоятельствах этот конкретный график двух потоков может никогда не возникнуть, и состояние гонки может никогда не проявиться.Только при других обстоятельствах, возможно, при работе в сильно загруженной системе (или на новом многопроцессорном сервере важного клиента!) Ошибка может проявиться.
Чтобы устранить условия гонки, вам нужен способ сделать операции атомарными.Атомная операция неделима и беспрерывна;после начала операции она не будет приостановлена или прервана до ее завершения, и никакая другая операция не будет выполняться в это время.В этом конкретном примере вы хотите проверить job_queue;если он не пустой, удалите первое задание, все как одну атомарную операцию.