תרגול 9 – סינכרוניזציה ב-Linux

Slides:



Advertisements
Podobné prezentace
Funkce Připomeňme si program pro výpočet faktoriálu:
Advertisements

Programovací jazyk C++
Přednáška 11 Jiří Šebesta
PB071 Úvod do C, PB071 – Programování v jazyce C POSIX.
Pole, ukazatele a odkazy
Informační systémy Realizace uložených procedur a spouští, jejich praktické využití.
Preprocess Úvod do tvorby funkcí Princip preprocesoringu Direktivy preprocesoru Podmíněný překlad Základy tvorby funkcí Zjednodušený popis principu předávaní.
Paralelní programování
Paralelní programování
Paralelní programování
Větvení cykly J a v a Začínáme programovat Lucie Žoltá.
Fronty (Queue) v JDK 1.5 (1.6) Java.vse.cz.
MySQL - Vytvoření nové tabulky  create table jméno_tabulky (jméno_položky typ_položky,... ) Přehled nejběžnějších datových typů Přehled nejběžnějších.
A1PRG - Programování – Seminář Ing. Michal Standardní knihovní funkce pro práci se soubory 13 Verze
Datové struktury a algoritmy Část 11 Rozptylování - Hashing
OSNOVA: a) Řetězce v C b) Funkce stdio.h pro řetězce c) Funkce string.h pro řetězce d) Příklad Jiří Šebesta Ústav radioelektroniky, FEKT VUT v Brně Počítače.
PB161 – Programování v jazyce C++ Objektově Orientované Programování
Podpora vláken a jejich synchronizace v jazyce C# Jan Kučera Jan Mittner Petr Effenberger 4IT353 Klient/server aplikace v Javě.
Příklady v jazyku C – část 6
PRÁCE S VLÁKNY A APLIKAČNÍ DOMÉNY V.NET FRAMEWORK APLIKACÍCH Architektura technologie.NET Jan Martinovič, FEI - Katedra Informatiky.
Příklady v jazyku C – část 4
Příklady v jazyku C – část 3
13AMP 3. přednáška Ing. Martin Molhanec, CSc.. Co jsme se naučili naposled I. Co je to kontext úlohy Co je to kontext úlohy Task switching (přepnutí úlohy)
12/04/20151 Kolekce (1) Kolekce (collection) představují standardní datové struktury (seskupení) prvků (objektů) Jsou definovány ve jmenném prostoru System.Collections.
Příklady v jazyku C – část 2
OSNOVA: a) Příkazy pro větvení b) Příkazy pro cykly c) Příkazy pro řízení přenosu d) Příklad Jiří Šebesta Ústav radioelektroniky, FEKT VUT v Brně Počítače.
Knihovna GLib ● Multiplatformní nástavba standardní C knihovny (běží na Windows, Linux, Mac,...) ● Naleznete zde nástroje pro komfortní práci s řetězci.
Realloc a qsort examples BI-PA1 Programování a algoritmizace 1 Katedra teoretické informatiky © Miroslav Balík Fakulta informačních technologií České vysoké.
1 / 2X36DSA 2005The complexity of different algorithms varies: O(n), Ω(n 2 ), Θ(n·log 2 (n)), … Různé algoritmy mají různou složitost: O(n), Ω(n 2 ), Θ(n·log.
1 / 9X36DSA 2005The complexity of different algorithms varies: O(n), Ω(n 2 ), Θ(n·log 2 (n)), … Různé algoritmy mají různou složitost: O(n), Ω(n 2 ), Θ(n·log.
A4B33OSS (J. Lažanský) verze: Podzim 2010 Meziprocesní komunikace a synchronizace procesů 1 Obsah Téma 5 – Meziprocesní komunikace a synchronizace procesů.
13AMP 4. přednáška Ing. Martin Molhanec, CSc.. Co jsme se naučili naposled Problém sdílených zdrojů Problém sdílených zdrojů Co je to kritická sekce Co.
C – jak na procedury Mgr. Lenka Švancarová. C – procedury #include int main() { printf("Ahoj\n"); return(0); } #include void pozdrav(void) { printf("Ahoj\n");
Příklady v jazyku C – část 8. Napište program, který inicializuje 2-rozměrné pole uživatele (5 řádků, 2 sloupce) a naplní ho hodnotami (první sloupec.
PŘÍKAZ while úkol 1_42.
Vazby dynamických proměnných,databázové systémy Přednáška č. 10.
Soubory BI-PA1 Programování a algoritmizace 1, ZS Katedra teoretické informatiky © Miroslav Balík Fakulta informačních technologií České vysoké.
ZÁKLADNÍ POJMY. ZDROJOVÝ TEXT PROGRAMU Tvoří: klíčová slova komentáře identifikátory.
Jazyk C A0B36PRI - PROGRAMOVÁNÍ Část II.
Příklady v jazyku C – část 2
C – procedury Mgr. Lenka Švancarová.
Základy operačních systémů Meziprocesová komunikace a synchronizace Jakub Yaghob.
ארץ של כפור ואש צביקה שיאון ISLAND ÚZEMÍ MRAZU I OHNĚ.
Úvod do UNIXu (6th round)
1 / 3The complexity of different algorithms varies: O(n), Ω(n 2 ), Θ(n·log 2 (n)), … Různé algoritmy mají různou složitost: O(n), Ω(n 2 ), Θ(n·log 2 (n)),
1/34 PB153 OPERAČNÍ SYSTÉMY A JEJICH ROZHRANÍ Synchronizace procesů 08.
C-Sim verze 5.0. Charakteristika Softwarový nástroj pro simulaci v diskrétním čase Použitá metodou paralelních procesů Navržen podle vzoru jazyka SIMULA.
שערוך דופק מפרק כף היד מנחה : ד " ר לנגה דני מאת : די - קסטרו דותן בר - יוסף גיל מרץ 2003 The Physiological Signal Processing Laboratory.
תרגיל מס' 2: מבנה ותפקוד חלבונים- המוגלובין
פורמולציות מסיסות מים של תמציות טבעיות בעלות פעילות אנטי-פטרייתית
השוואת תמונות ע ” י מרחק האוסדורף לפי הזזה. מבוא בעיה מרכזית בזיהוי צורות היא קביעת גודל הדמיון בין שתי צורות האלגוריתמים שנציג מבוססים על השוואת שני.
מערכות הפעלה תרגול 7 – סינכרוניזציה ב-Linux. מערכות הפעלה - תרגול 72 (c) ארז חדד 2003 תוכן התרגול מבוא לסינכרוניזציה ב-Linux סנכרון בין חוטי POSIX  mutex.
Uživatelská rozhraní Cvičení 12a Martin Němec A
Uživatelská rozhraní Uživatelská rozhraní. knihovna Qt Trolltech (1994) v Oslu (Norsko) vytváří grafické uživatelské rozhraní (GUI) pro C++ multi-platformová.
Y36PJC Programování v jazyce C/C++
PB071 – Principy nízkoúrovňového programování
NPRG051 Pokročilé programování v C++
Otevři mi oči, ať pozoruji divy tvého zákona (tóry). ( Ž 119,18)
Y36PJC Programování v jazyce C/C++
VÝVOJ PODNIKOVÝCH APLIKACÍ NA PLATFORMĚ JAVA - CVIČENÍ
Programování mikropočítačů
התגבשות של תחמוצות ברזל בסביבה היפר-סלינית באזור ים המלח
NPRG051 Pokročilé programování v C++
ערכת חיתוך ופישוק - לוקאס
Úvod do jazyka C Algoritmizácia úloh.
PB071 – Principy nízkoúrovňového programování
private var hodnota:number
Přednášky z Distribuovaných systémů
Fronta (1) Dynamická datová struktura typu FIFO (First In First Out)
Přednášky z Distribuovaných systémů
Transkript prezentace:

תרגול 9 – סינכרוניזציה ב-Linux מערכות הפעלה תרגול 9 – סינכרוניזציה ב-Linux

תרגול 9 – סינכרוניזציה ב-Linux תוכן התרגול מבוא לסינכרוניזציה ב-Linux סנכרון בין חוטי POSIX mutex סמפורים condition variable דוגמה: מימוש מנעול קוראים-כותבים. (c) ארז חדד 2003 תרגול 9 – סינכרוניזציה ב-Linux

מבוא לסינכרוניזציה ב-Linux הצורך בסנכרון הקשרי ביצוע שונים (כגון חוטים ותהליכים) הינו חיוני בכל מערכת הפעלה. Linux מספקת מגוון רחב של מנגנונים לסנכרון בין חוטים ותהליכים, הן כשירות לקוד משתמש והן לצורך שימוש עצמי בספריות ובגרעין. בתרגול זה נציג את עיקר מנגנוני הסנכרון עבור חוטים ברמת המשתמש (API). (c) ארז חדד 2003 תרגול 9 – סינכרוניזציה ב-Linux

סנכרון בין חוטי POSIX ב-Linux Linux Threads תומכת בחלק ממנגנוני הסנכרון המוגדרים ב-POSIX mutexes סמפורים (POSIX 1003.1b) ...רק עבור חוטים (לא בין תהליכים) condition variables תמיכה ב-monitors אין תמיכה במנעולי קוראים-כותבים ...אבל ניתן לממש מנעולים כאלה, כפי שנראה בהמשך (c) ארז חדד 2003 תרגול 9 – סינכרוניזציה ב-Linux

תרגול 9 – סינכרוניזציה ב-Linux מנעולי mutex סנכרון בין חוטי POSIX ב-Linux מנעול mutex מאפשר לחוט אחד בדיוק להחזיק בו (לנעול אותו). כל חוט אחר המבקש להחזיק במנעול ייחסם עד אשר המנעול ישוחרר רק החוט המחזיק במנעול אמור לשחרר אותו (בעלות על המנעול) מנעולי mutex משמשים בדרך-כלל להגנה על גישה לנתונים משותפים, בתוך קטע קוד קריטי, ע"י נעילת המנעול בכניסה לקטע הקריטי ושחרורו בסופו. (c) ארז חדד 2003 תרגול 9 – סינכרוניזציה ב-Linux

פעולות על מנעולי mutex (1) סנכרון בין חוטי POSIX ב-Linux #include <pthread.h> אתחול mutex לפני השימוש: int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutex_attr_t *mutexattr); פינוי mutex בתום השימוש int pthread_mutex_destroy(pthread_mutex_t *mutex); הפעולה נכשלת אם ה-mutex מאותחל, אבל נעול (c) ארז חדד 2003 תרגול 9 – סינכרוניזציה ב-Linux

פעולות על מנעולי mutex (2) סנכרון בין חוטי POSIX ב-Linux נעילת mutex: int pthread_mutex_lock(pthread_mutex_t *mutex); הפעולה חוסמת עד שה-mutex מתפנה ואז נועלת אותו נסיון לנעילת mutex: int pthread_mutex_trylock(pthread_mutex_t *mutex); הפעולה נכשלת אם ה-mutex כבר נעול, אחרת נועלת אותו. שחרור mutex נעול: int pthread_mutex_unlock(pthread_mutex_t *mutex); (c) ארז חדד 2003 תרגול 9 – סינכרוניזציה ב-Linux

פעולות על מנעולי mutex (3) סנכרון בין חוטי POSIX ב-Linux פרמטרים: mutex – המנעול עליו מבוצעת הפעולה mutexattr – מגדיר את תכונות ה-mutex ב-Linux Threads מוגדרת רק תכונת "סוג" ה-mutex, המתבטאת בהתנהגות ה-mutex בנעילה ובשחרור, כמוצג בשקף הבא ברירת המחדל – NULL – mutex מסוג "מהיר" מומלץ לעבוד עם mutex מסוג "בודק שגיאות", כדי למנוע מצבים בעייתיים כגון אלו המסומנים באדום בשקף הבא פרטים כיצד לבחור את סוג ה-mutex ב-man pages ערך מוחזר: 0 בהצלחה, ערך אחר בכישלון (c) ארז חדד 2003 תרגול 9 – סינכרוניזציה ב-Linux

תרגול 9 – סינכרוניזציה ב-Linux סוגים של מנעולי mutex סנכרון בין חוטי POSIX ב-Linux סוג ה-mutex נעילה חוזרת ע"י החוט המחזיק במנעול שחרור מנעול ע"י חוט שאינו מחזיק במנעול שחרור מנעול ע"י החוט המחזיק במנעול mutex מהיר DEADLOCK מותר mutex רקורסיבי מגדיל מונה נעילה עצמית ב-1 מקטין מונה נעילה עצמית ב-1. ה-mutex נשאר נעול עד שהמונה מגיע ל-0 mutex בודק שגיאות כשלון (c) ארז חדד 2003 תרגול 9 – סינכרוניזציה ב-Linux

תרגול 9 – סינכרוניזציה ב-Linux דוגמה: מנעולי mutex סנכרון בין חוטי POSIX ב-Linux להלן דוגמה המשתמשת ב-mutex: pthread_mutex_t m; int count; void update_count() { pthread_mutex_lock(&m); count = count * 5 + 2; pthread_mutex_unlock(&m); } int get_count() { int c; pthread_mutex_lock(&m); c = count; pthread_mutex_unlock(&m); return c; } מדוע צריך להגן על הגישה ל-count בתוך update_count()? כדי למנוע שיבוש ערך count בעדכונים מחוטים שונים. מדוע צריך להגן על הגישה ל-count בתוך get_count()? כדי למנוע קבלת תוצאות חלקיות הנוצרות במהלך העדכון שימו לב! גם אם ביטוי ההגדלה היה count++, לא מובטח שהקוד הנפרש באסמבלר הינו אטומי, ולכן יש להפעיל מנגנון סנכרון לפי הצורך. (c) ארז חדד 2003 תרגול 9 – סינכרוניזציה ב-Linux

תרגול 9 – סינכרוניזציה ב-Linux סמפורים כלליים סנכרון בין חוטי POSIX ב-Linux סמפור ממומש ב-Linux Threads בערך כמו שתואר בהרצאה: לכל סמפור יש מונה, תור ומנעול שתפקידו להגן על הקוד של הפעולות של הסמפור (פעולות אטומיות) שתי פעולות בסיסיות על הסמפור: wait: אם המונה גדול מ-0, מקטינה אותו ב-1, אחרת החוט נכנס להמתנה בתור. בהרצאה הקטנו גם אם המונה קטן מ-0. post: אם תור הממתינים לא ריק, מוציאה ומעירה את החוט הראשון בתור, אחרת מגדילה את המונה ב-1 בהרצאה קראנו ל-post בשם signal. תור הממתינים הוגן (FIFO) לפי עדיפויות, כלומר חוט בעדיפות גבוהה יצא מהתור לפני חוט בעדיפות נמוכה (c) ארז חדד 2003 תרגול 9 – סינכרוניזציה ב-Linux

תרגול 9 – סינכרוניזציה ב-Linux פעולות על סמפורים (1) סנכרון בין חוטי POSIX ב-Linux #include <semaphore.h> לא לשכוח לקשר לספרייה pthread! אתחול סמפור לפני השימוש: int sem_init(sem_t *sem, int pshared, unsigned int value); פינוי סמפור בתום השימוש: int sem_destroy(sem_t *sem); (c) ארז חדד 2003 תרגול 9 – סינכרוניזציה ב-Linux

תרגול 9 – סינכרוניזציה ב-Linux פעולות על סמפורים (2) סנכרון בין חוטי POSIX ב-Linux ביצוע wait על סמפור: int sem_wait(sem_t *sem); ביצוע post על סמפור: int sem_post(sem_t *sem); גרסה לא-חוסמת של wait: int sem_trywait(sem_t *sem); אם המונה של הסמפור אינו גדול מ-0, חוזרת מיד ונכשלת קריאת ערך מונה הסמפור: int sem_getvalue(sem_t *sem, int *sval); (c) ארז חדד 2003 תרגול 9 – סינכרוניזציה ב-Linux

תרגול 9 – סינכרוניזציה ב-Linux פעולות על סמפורים (3) סנכרון בין חוטי POSIX ב-Linux פרמטרים: sem – הסמפור עליו מבוצעות הפעולות. pshared – אם ערכו גדול מ-0, מציין שהסמפור יכול להיות משותף למספר תהליכים. תכונה זו אינה נתמכת, ולכן נציב בו 0 קבוע. value – ערכו ההתחלתי של מונה הסמפור. sval – מצביע למקום בו יאוחסן ערך מונה הסמפור. ערך מוחזר: 0 בהצלחה, (1-) בכישלון הפונקציות sem_wait() ו-sem_getvalue() תמיד מצליחות. (c) ארז חדד 2003 תרגול 9 – סינכרוניזציה ב-Linux

תרגול 9 – סינכרוניזציה ב-Linux הערות על סמפורים סנכרון בין חוטי POSIX ב-Linux סמפור המאותחל עם מונה בערך 1 נקרא סמפור בינארי. סמפור בינארי יכול לשמש להגנה על קטע קריטי (ליצור מניעה הדדית בין החוטים הניגשים). סמפור בינארי אינו מנעול mutex, משום שכל חוט יכול לבצע post על סמפור, גם אם לא ביצע wait על הסמפור קודם לכן (אין "בעלות" על הסמפור). (c) ארז חדד 2003 תרגול 9 – סינכרוניזציה ב-Linux

תרגול 9 – סינכרוניזציה ב-Linux משתני תנאי סנכרון בין חוטי POSIX ב-Linux נתבונן בבעיית מימוש תור. נרצה לסנכרן את פעולות ההכנסה וההוצאה מהתור, כך שחוט יוכל להוציא איבר מתור רק אם התור אינו ריק. בבעיה זו יש צורך לסנכרן בין חוטים המבצעים הוצאת והכנסת איברים כדי לשמור על תקינות מבנה הנתונים, וכן להמתין לאירוע כדי למנוע הוצאת איבר מתור ריק. משתנה תנאי (condition variable) – מאפשר לחוט להמתין לאירוע כלשהו, כפי שמוגדר ע"י המתכנת. משתנה תנאי תמיד קשור ל-mutex מסוים. mutex + 0 או יותר משתני תנאי ≈ מוניטור. (c) ארז חדד 2003 תרגול 9 – סינכרוניזציה ב-Linux

תרגול 9 – סינכרוניזציה ב-Linux פעולות על משתני תנאי (1) סנכרון בין חוטי POSIX ב-Linux #include <pthread.h> איתחול משתנה תנאי לפני השימוש: int pthread_cond_init(pthread_cond_t *cond, pthread_condattr_t *cond_attr); פינוי משתנה תנאי בסיום השימוש: int pthread_cond_destroy(pthread_cond_t *cond); הפעולה נכשלת אם יש חוטים הממתינים על משתנה התנאי (c) ארז חדד 2003 תרגול 9 – סינכרוניזציה ב-Linux

תרגול 9 – סינכרוניזציה ב-Linux פעולות על משתני תנאי (2) סנכרון בין חוטי POSIX ב-Linux המתנה על משתנה תנאי: int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex); החוט הממתין חייב להחזיק במנעול mutex לפני הקריאה פעולה אטומית: משחררת את המנעול mutex ומעבירה את החוט להמתין על משתנה התנאי (c) ארז חדד 2003 תרגול 9 – סינכרוניזציה ב-Linux

תרגול 9 – סינכרוניזציה ב-Linux פעולות על משתני תנאי (3) סנכרון בין חוטי POSIX ב-Linux שחרור חוט ממתין על משתנה תנאי: int pthread_cond_signal(pthread_cond_t *cond); אם אין חוט שממתין כרגע על משתנה התנאי cond – הפעולה חסרת השפעה (ואינה נזכרת הלאה). אם קיימים חוטים ממתינים על משתנה התנאי cond – אחד החוטים הממתינים (הגינות לא מובטחת) מפסיק להמתין על משתנה התנאי.החוט הנ"ל עובר להמתין על ה-mutex ויחזור לפעילות (יעבור את ה-pthread_cond_wait()) לאחר שינעל מחדש את ה-mutex (סגנון Mesa). (c) ארז חדד 2003 תרגול 9 – סינכרוניזציה ב-Linux

תרגול 9 – סינכרוניזציה ב-Linux פעולות על משתני תנאי (4) סנכרון בין חוטי POSIX ב-Linux שחרור כל החוטים הממתינים על משתנה תנאי: int pthread_cond_broadcast(pthread_cond_t *cond); אם אין חוט שממתין כרגע על משתנה התנאי cond – הפעולה חסרת השפעה (ואינה נזכרת הלאה). אם קיימים חוטים ממתינים על משתנה התנאי cond – כל החוטים הממתינים מפסיקים להמתין על משתנה התנאי ועוברים להמתין על ה-mutex.החוטים יחזרו לפעילות בזה אחר זה (בסדר כלשהו, לאו דווקא הוגן) לאחר שינעלו מחדש את ה-mutex. (c) ארז חדד 2003 תרגול 9 – סינכרוניזציה ב-Linux

תרגול 9 – סינכרוניזציה ב-Linux פעולות על משתני תנאי (5) סנכרון בין חוטי POSIX ב-Linux פרמטרים: cond – משתנה התנאי עליו מבוצעת הפעולה cond_attr – מגדיר את תכונות משתנה התנאי ב-Linux Threads אין משמעות לפרמטר זה. ערך NULL mutex – המנעול אליו משויך משתנה התנאי בביצוע pthread_cond_wait() ערך מוחזר: 0 בהצלחה, ערך אחר בכישלון הפונקציות init, signal, broadcast, wait תמיד מחזירות ערך הצלחה. (c) ארז חדד 2003 תרגול 9 – סינכרוניזציה ב-Linux

קישור בין אירוע ומשתנה תנאי (1) הדרך הפשוטה ביותר לקשר בין אירוע המציין קיום מצב רצוי כלשהו למשתנה תנאי היא בקוד כדלקמן: אצל הממתין לאירוע (החוט שרוצה להתקדם רק כאשר יושג המצב הרצוי): if <לא מתקיים המצב הרצוי> pthread_cond_wait(<משתנה התנאי>, <מנעול>); <המשך הקוד> אצל יוצר האירוע (החוט שיוצר את המצב הרצוי ומסמן לחוטים הממתינים להתקדם): if <מתקיים המצב הרצוי> אם זה ודאי ifאפשר לוותר על ה- pthread_cond_signal(<משתנה התנאי>); (c) ארז חדד 2003 תרגול 9 – סינכרוניזציה ב-Linux

קישור בין אירוע ומשתנה תנאי (2) נתבונן במימוש של תור כפי שהופיע בהרצאה pthread_mutex_t qlock; pthread_cond_t notEmpty; /* … initialization code … */ void enqueue(item x) { pthread_mutex_lock(&qlock); /* … add x to queue … */ pthread_cond_signal(&notEmpty); pthread_mutex_unlock(&qlock); } item dequeue() { pthread_mutex_lock(&qlock); if <queue is empty> pthread_cond_wait(&notEmpty,&qlock); /* … remove item from queue … */ pthread_mutex_unlock(&qlock); /* .. return removed item */ } האם מימוש זה פותר את הבעיה ? לא ! לפי המימוש הנ"ל יתכן מצב של הוצאת איבר מתור ריק . באו נראה איך ... (c) ארז חדד 2003 תרגול 9 – סינכרוניזציה ב-Linux

קישור בין אירוע ומשתנה תנאי (3) פעולת signal לא מאפשרת לחוט הממתין להמשיך מיד. החוט הממתין צריך תחילה לנעול את ה-mutex מחדש (סגנון Mesa). ייתכן שלפני שהחוט הממתין ינעל את ה-mutex מחדש יספיק להכנס חוט נוסף שישנה את הנתונים כך שהמצב הרצוי כבר לא מתקיים. (c) ארז חדד 2003 תרגול 9 – סינכרוניזציה ב-Linux

קישור בין אירוע ומשתנה תנאי (4) נניח, לפי הדוגמה שהתור ריק וחוט t1 קורא ל-dequeue(), ולכן ממתין כעת חוט t2 קורא ל-enqueue(), מכניס איבר לתור ומבצע signal חוט t1 עובר להמתין לשחרור המנעול כעת מגיע חוט t3, וקורא ל-dequeue() חוט t3 נחסם בהמתנה למנעול בתחילת הקוד חוט t2 משחרר את המנעול ומסיים את enqueue() חוט t3 מקבל את המנעול, נכנס, מוציא איבר ומסיים חוט t1 מקבל את המנעול, ממשיך לבצע את הקוד ומנסה להוציא איבר מתור ריק! (c) ארז חדד 2003 תרגול 9 – סינכרוניזציה ב-Linux

קישור בין אירוע ומשתנה תנאי (5) ממה נבעה הבעיה בדוגמה? מכך שהתנאי של האירוע לא נבדק אחרי ה-wait כיצד ניתן לפתור את הבעיה? ע"י בדיקה חוזרת של תנאי האירוע והמתנה נוספת לפי הצורך. לדוגמה: while <queue is empty> pthread_cond_wait(…) האם הבעיה יכלה לקרות גם אם המנעול היה הוגן (תור FIFO)? כן! אם t3 היה קורא ל-dequeue() ומחכה למנעול לפני ש-t2 הגיע ל-signal (c) ארז חדד 2003 תרגול 9 – סינכרוניזציה ב-Linux

מימוש מוניטור בנוסח Hoare במימוש לפי סגנון Hoare (נדיר מאוד), החוט שמבצע signal גם מוותר על המנעול ומעביר אותו לחוט הממתין. באופן זה מצב הנתונים לא משתנה, והחוט הממתין ממשיך ללא הפרעה במצב הרצוי. מצד שני, בסגנון Hoare החוט שביצע signal נענש על כך שסייע לחוט אחר להתקדם מוותר על ההתקדמות שלו וממתין עד שהמנעול משוחרר. האם הבעיה שראינו בדוגמה של התור יכולה לקרות אם ה-monitor היה בסגנון Hoare? לא! כי t1 היה מקבל את המנעול לפני t3 (c) ארז חדד 2003 תרגול 9 – סינכרוניזציה ב-Linux

תרגול 9 – סינכרוניזציה ב-Linux מנעול קוראים-כותבים סנכרון בין חוטי POSIX ב-Linux משאב עם שתי פעולות: קריאה וכתיבה מספר חוטים קוראים יכולים לגשת למשאב בו-זמנית חוט כותב צריך גישה בלעדית למשאב בשקפים הבאים נדגים כיצד ניתן לממש מנעול קוראים-כותבים באמצעות monitor בהרצאה ראינו איך להשתמש בסמפור למטרה זו. תזכורת מההרצאה! (c) ארז חדד 2003 תרגול 9 – סינכרוניזציה ב-Linux

מימוש מנעול קוראים-כותבים (1) סנכרון בין חוטי POSIX ב-Linux הגדרת המנגנון: #include <pthread.h> int number_of_readers; pthread_cond_t readers_condition; int number_of_writers; pthread_cond_t writers_condition; mutex_t global_lock; void readers_writers_init() { number_of_readers = 0; pthread_cond_init(&readers_condition, NULL); number_of_writers = 0; pthread_cond_init(&writers_condition, NULL); pthread_mutex_init(&global_lock, NULL); } מספר החוטים שקוראים מהמשאב אירוע: מותר לקרוא מספר החוטים שכותבים למשאב אירוע: מותר לכתוב (c) ארז חדד 2003 תרגול 9 – סינכרוניזציה ב-Linux

מימוש מנעול קוראים-כותבים (2) סנכרון בין חוטי POSIX ב-Linux void read_lock() { pthread_mutex_lock(&global_lock); while (number_of_writers > 0) pthread_cond_wait(&readers_condition, &global_lock); number_of_readers++; pthread_mutex_unlock(&global_lock); } <Read Data> void read_unlock() { number_of_readers--; if (number_of_readers == 0) pthread_cond_signal(&writers_condition); צריך לבדוק את תנאי הבדיקה גם לאחר wait 1 (c) ארז חדד 2003 תרגול 9 – סינכרוניזציה ב-Linux

מימוש מנעול קוראים-כותבים (3) סנכרון בין חוטי POSIX ב-Linux void write_lock() { pthread_mutex_lock(&global_lock); while ((number_of_writers > 0) || (number_of_readers > 0)) pthread_cond_wait(&writers_condition, &global_lock); number_of_writers++; pthread_mutex_unlock(&global_lock); } <Write Data> void write_unlock() { number_of_writers--; if (number_of_writers == 0) { pthread_cond_broadcast(&readers_condition); pthread_cond_signal(&writers_condition); צריך לבדוק את תנאי הבדיקה גם לאחר wait למעשה, אין צורך ב-if.. 2 עדיפות לקוראים ממתינים על-פני כותבים ממתינים? (c) ארז חדד 2003 תרגול 9 – סינכרוניזציה ב-Linux

תרגול 9 – סינכרוניזציה ב-Linux חסרונות של המימוש כל עוד המנעול אצל הקוראים, קורא חדש שמגיע יצליח להיכנס ויעקוף כותבים שהגיעו לפניו. חוסר הוגנות והרעבה אפשרית של הכותבים. לא ניתן לדעת האם הקוראים או הכותב יכנסו לקטע הקריטי תלוי מי יצליח לתפוס ראשון את המנעול. האם ואיך אפשר לפתור בעיות אלו? 1 2 (c) ארז חדד 2003 תרגול 9 – סינכרוניזציה ב-Linux