Синхронизация потоков в ОС Linux, страница 3

while (!thread_done) pthread_cond_wait(&rx, &my_sync);

x++;

printf("Main thread increments X, after that X value is %d\n",x);

pthread_mutex_unlock(&my_sync);

exit(0);

}

void* compute_thread(void* dummy) {

printf("X value in thread before sleep = %d\n",x);

printf("X value in thread is incremented by 1 before sleep\n");

pthread_mutex_lock (&my_sync);

x++;

sleep(2);

printf("X value in thread after sleep = %d\n",x);

thread_done = 1;

pthread_cond_signal (&rx);

pthread_mutex_unlock (&my_sync);

return;

}

Задание на лабораторную работу:

1.  Выполните следующие действия. Для каждого изменения опишите, что происходит, и дайте объяснение – почему.

a.  Уберите в первом примере функцию sleep.

b.  Уберите во втором примере функцию освобождения мьютекса из порожденного потока.

c.  Уберите в третьем примере функцию pthread_cond_signal.

2.  Решите классическую проблему «поставщик – потребитель» с использованием описанных в лабораторной работе средств синхронизации. Постановка задачи: Один поток производит данные, другой поток их потребляет. В промежуток времени между изготовлением и потреблением данные хранятся в буфере. Пример использования: Конвейер команд в Unix. Исходные данные: Данные хранятся в циклическом буфере. Циклический буфер описывается некоторой областью памяти, указателем начала данных и указателем конца данных. Поток-поставщик записывает данные в конец буфера, поток-потребитель считывает их с начала буфера. После записи или чтения соответствующим образом меняются указатели начала и конца.

Операции чтения/записи должны быть выполнены как взаимоисключающие. Если операция чтения выполняется над пустым буфером (указатель начала = указатель конца), поток-потребитель должен быть заблокирован на условной переменной до тех пор, пока поток-поставщик не запишет в буфер какие-нибудь данные. Если операция записи выполняется над полным буфером, поток-поставщик должен также быть заблокирован на условной переменной до тех пор, пока поток-потребитель не считает из буфера какие-нибудь данные. Размер буфера – 10 символов. Поток-поставщик и поток-потребитель работают в бесконечном цикле. Поток-поставщик производит по одному символу в последовательности 0,1,2...9,0,1,... и записывает его в буфер через случайный интервал времени 0,5 – 2 сек. Поток-потребитель считывает по одному символу через случайный интервал времени 0,5 – 2 сек из буфера и выводит их на экран в виде сообщений (например, Символ 0, Символ 1,...) Примерное решение: Произвести() { захватить мьютекс; if(буфер полный) ждать(буфер_неполный); произвести символ; буфер[next_in]=символ; next_in=(next_in+1)%(размер_буфера); сигнал(буфер_непустой); освободить мьютекс; ждать случайное время; } Потребить() { захватить мьютекс; if(буфер пустой) ждать(буфер_непустой); символ=буфер[next_out]; next_out=(next_out+1)%(размер_буфера); сигнал(буфер_неполный); освободить мьютекс; ждать случайное время; }

Содержание отчета по лабораторной работе:

1.  Текст и результат работы программы.

2.  Ответы на вопросы.

3.  Вывод.