1 / 16

Другие примитивы синхронизации

Другие примитивы синхронизации. Программирование с использованием POSIX thread library. Блокировки чтения / записи. pthread_rwlock_init pthread_rwlock_rdlock pthread_rwlock_wrlock pthread_rwlock_unlock pthread_rwlock_destroy. Pthread_rwlock_init(3C). #include <pthread.h>

qamar
Télécharger la présentation

Другие примитивы синхронизации

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Другие примитивы синхронизации Программирование с использованием POSIX thread library

  2. Блокировки чтения/записи • pthread_rwlock_init • pthread_rwlock_rdlock • pthread_rwlock_wrlock • pthread_rwlock_unlock • pthread_rwlock_destroy

  3. Pthread_rwlock_init(3C) #include <pthread.h> int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock, const pthread_rwlockattr_t *restrict attr); pthread_rwlock_t rwlock=PTHREAD_RWLOCK_INITIALIZER; int pthread_rwlock_destroy(pthread_rwlock_t **rwlock);

  4. pthread_rwlock_rdlock(3C) #include <pthread.h> int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock); int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock);

  5. pthread_rwlock_wrlock(3C) #include <pthread.h> int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock); int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock);

  6. Свойства блокировок чтения/записи • Несколько нитей могут одновременно держать одну и ту же блокировку на чтение • Блокировка на чтение рекурсивна (одна нить может захватывать ее несколько раз) • Блокировку на запись может держать только одна нить. При этом никто не может держать ту же блокировку на чтение. • Блокировка на запись нерекурсивна

  7. Условные переменные • pthread_cond_init • pthread_cond_wait • pthread_cond_signal • pthread_cond_broadcast • pthread_cond_destroy

  8. pthread_cond_init(3C) #include <pthread.h> int pthread_cond_init(pthread_cond_t *restrict cond, const pthread_condattr_t *restrict attr); pthread_cond_t cond= PTHREAD_COND_INITIALIZER; int pthread_cond_destroy(pthread_cond_t *cond);

  9. pthread_cond_wait(3C) #include <pthread.h> int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex); int pthread_cond_timedwait(pthread_cond_t *restrict cond,pthread_mutex_t *restrict mutex, const struct timespec *restrict abstime); /* Solaris only */ int pthread_cond_reltimedwait_np(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *reltime);

  10. Pthread_cond_signal(3C) #include <pthread.h> int pthread_cond_signal( pthread_cond_t *cond); int pthread_cond_broadcast( pthread_cond_t *cond);

  11. Что же такое условная переменная • «Культурный» способ организации холостого цикла. • Идея в том, что условная переменная защищает какой-то предикат (условие). • Вызов pthread_cond_signal(3C)/broadcast означает, что это условие, возможно, изменилось • Это не означает, что оно действительно изменилось • Т.е. после пробуждения из wait предикат обязательно надо снова проверить. • Это касается не только timedwait, но и простого wait • Стандарт POSIX допускает ложные сработки, т.е. выход из cond_wait без вызова кем-либо signal

  12. Еще про условную переменную • Всегда применяется в паре с мутексом. • Перед вызовом pthread_cond_wait(3C) мутекс должен быть захвачен • При входе в wait мутекс освобождается, при пробуждении снова захватывается • В соответствии с Solaris man, нельзя использовать одну и ту же переменную с разными мутексами (результат не определен) • Мутекс должен защищать данные, используемые при вычислении предиката

  13. Применение условной переменной • Задача производитель-потребитель • Если решать только на мутексах, нужно 3 мутекса и холостой цикл на входе • Решается с одним мутексом и одной условной переменной (т.е. условная переменная ~ эквивалентна 2 мутексам)

  14. Открытие файлов • Многопоточная программа открывает много файлов. • Например, задача «Многопоточный cp –R» • Если ручки файлов кончаются, надо подождать, пока кто-то закроет файл.

  15. Открытие файлов - пример pthread_mutex_lock(&fileopen_mutex); do { srcfile=open(srcpathname, O_RDONLY, 0); if (srcfile < 0 && errno!=EMFILE) { perror(dstpathname); pthread_mutex_unlock(&fileopen_mutex); return NULL; } if (srcfile>0) { dstfile=open(dstpathname, O_WRONLY | O_CREAT, stat.st_mode); if (dstfile < 0 && errno != EMFILE) { perror(dstpathname); close(srcfile); pthread_cond_signal(&fileopen_cond); pthread_mutex_unlock(&fileopen_mutex); return NULL; } } if (srcfile<0 || dstfile <0) { if (srcfile>0) { close(srcfile); pthread_cond_signal(&fileopen_cond); } /* printf("waiting for file handles - opening file %s or %s\n", srcpathname, dstpathname); */ pthread_cond_wait(&fileopen_cond, &fileopen_mutex); } } while(dstfile<0 || srcfile<0); pthread_mutex_unlock(&fileopen_mutex);

  16. Атомарный захват нескольких мутексов voidget_forks (int phil,int fork1,int fork2){ int res; pthread_mutex_lock(&getting_forks_mx); do { if (res=pthread_mutex_trylock(&forks[fork1])) { res=pthread_mutex_trylock(&forks[fork2]); if (res) pthread_mutex_unlock(&forks[fork1]); } if (res) pthread_cond_wait(&getting_forks_cond, &getting_forks_mx); } while(res); pthread_mutex_unlock(&getting_forks_mx); } void down_forks (int f1,int f2){ pthread_mutex_lock(&getting_forks_mx); pthread_mutex_unlock (&forks[f1]); pthread_mutex_unlock (&forks[f2]); pthread_cond_broadcast(&getting_forks_cond); pthread_mutex_unlock(&getting_forks_mx); }

More Related