Transcript Mutex

‫برنامه نويسي چند نخي با ‪POSIX‬‬
‫استاد‪ :‬دکتر پارسا‬
‫ارائه دهنده‪ :‬مهدي سخائي نيا‬
‫نيمسال دوم ‪88-89‬‬
‫فهرست مطالب‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫مفاهيم اوليه نخها‬
‫برنامه نويسي چند نخي‬
‫مدلهاي پياده سازي نخها‬
‫انواع مدلهاي نخ کشي‬
‫ايجاد و خاتمه نخ در ‪POSIX‬‬
‫قابليت الحاق‬
‫ارتباط بين نخها و همگام سازي‬
‫‪2‬‬
‫نخ (‪)thread‬‬
‫‪‬‬
‫نخ يک جريان اجرايي در فرآيند(‪ )process‬مي باشد که‬
‫مي‪ -‬تواند بصورت مستقل‪ ،‬توسط هسته زمانبندي گردد‬
‫و از فضاي آدرسي يکسان باساير نخها به اشتراک‬
‫استفاده نمايد‪.‬‬
‫‪3‬‬
‫مستقل بودن‬
‫‪‬‬
‫چون نخها بصورت مستقل زمانبندي مي شوند‪ ،‬نخها‬
‫بصورت همروند با ساير نخها اجرا مي شوند و امکان‬
‫اجراي موازي در سيستمهاي چند پردازنده اي وجود‬
‫دارد‪ .‬اين بدين معناست که هر نخ بايد منابع مربوط به‬
‫خودش داشته باشد‪:‬‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫شمارنده برنامه‬
‫فضاي پشته‬
‫مجموعه ثبات ( فضايي براي ذخيره کردن مقدار ثباتها‬
‫زماني که پردازنده در اختيار ندارد)‬
‫زمانبندي پردازنده )‬
‫اولويت(بهره گيري از ‪4‬‬
‫همروندي(‪)concurrency‬‬
‫‪‬‬
‫عمليات همروند هستند اگر امکان اجراي نوبتي آنها فراهم گردد‬
‫بنحويکه اجراي هر عمليات بصورت مستقل پيشرفت داشته‬
‫باشد‪.‬‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫نخها مي توانند براي استفاده از پردازنده با هر ترتيبي و با هر نخ‬
‫ديگر زمانبندي شوند‪ .‬ممکن است پردازنده از يک نخ در هر نقطه از‬
‫اجرايش گرفته شده و با نخ ديگري جايگزين شود‪.‬‬
‫عمليات که سبب توقف اجراي يک نخ شده‪ ،‬سبب توقف اجراي ساير‬
‫نخ ها نمي شود‪.‬‬
‫اگر ترتيب اجراي يک نخ مهم باشد يا يک نخ بايد قبل از اجراي نخ‬
‫ديگري کارش به پايان برسد‪ ،‬بنابراين اجراي نخ بايد براي هماهنگي‬
‫عمليات همگام گردد‪.‬‬
‫‪5‬‬
‫مزاياي برنامه نويسي چند نخي‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫بهره گيري از اجراي موازي بر روي معماري چند‬
‫پردازنده‪ -‬اي براي اجراي سريعتر‪.‬‬
‫افزايش کارايي روي معماري تک پردازنده اي بوسيله‬
‫فراهم آوردن امکان اجراي يک فرآيند بهنگام عمليات‬
‫ُکند ورودي‪-‬خروجي يا بالک شدن عملياتهاي ديگر‪.‬‬
‫پاسخدهي سريعتر در سيستمهاي بي درنگ و محاوره‬
‫اي که بايد به رخدادهاي ناهمگام پاسخ دهند‪.‬‬
‫‪6‬‬
‫مشکالت برنامه نويسي چند نخي‬
‫‪‬‬
‫سربار محاسباتي حاصل از همگام سازي و زمانبندي‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫در برنامه ها با امکان توازي سازي کم ممکن است قابل‬
‫تحمل نباشد‪.‬‬
‫نياز به دقت و نظم برنامه نويسي بيشتر براي طراحي و‬
‫هماهنگي ترتيبهاي اجراي مختلف‪.‬‬
‫اشکال زدايي مشکلتر‪.‬‬
‫‪7‬‬
POSIX






"Portable Operating System Interface [for Unix]"
POSIX
standard
for
thread
programming
interface(1995)
Implementations of POSIX standard are referred to
as POSIX threads or Pthreads.
Latest Edition IEEE std 1003.1,2004
Available for Linux and Unix OS family
Availabe for Windows

As Open Source http://sourceware.org/pthread-win32
8
‫پياده سازي نخ‬
‫‪‬‬
‫پياده سازي نخ در ‪ POSIX‬در سه اليه انتزاعي‬
‫‪9‬‬
‫اليه هاي انتزاعي‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫‪ Pthread‬توصيف ‪ POSIX‬براي رفتار نخها است که برنامه‬
‫نويس سيستم مستقيما از آن استفاده مي کند‪.‬‬
‫نخ سطح کرنل عنصري است که توسط کرنل‪ ،‬بعنوان متن‬
‫اجراي يک نخ در فرآيند‪ ،‬بطور واقعي ايجاد‪ ،‬زمانبندي و‬
‫مديريت مي شود‪ .‬چگونگي مديريت نخ وابسته به سيستم عامل‬
‫است‪.‬‬
‫کتابخانه يک روال پوششي است که فراخوان کرنل سيستم را‬
‫پياده سازي مي کند‪ .‬بعضا امکاناتي براي ايجاد‪ ،‬زمانبندي و‬
‫مديريت نخها مستقل از هسته فراهم مي شود که عنصر ايجاد‬
‫سطح کاربر ناميده مي شود‪.‬‬
‫شده توسط کتابخانه‪ ،‬نخ‬
‫‪10‬‬
‫سه مدل پياده سازي نخها‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫چند به يک‬
‫يک به يک‬
‫چند به چند‬
‫‪11‬‬
‫چند به يک‬
‫‪‬‬
‫‪ Pthread‬بعنوان نخ سطح کاربر پياده سازي مي شود‪.‬‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫کتابخانه زمان اجرا نيز در حالت کاربر قرار دارد و نخ را زمانبندي‬
‫مي کند‬
‫براي سيستم عامل قابل مشاهده نيستند‪.‬‬
‫هر فرايند به يک نخ سطح کرنل نگاشت مي شود‪.‬‬
‫مشخصات‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫قابليت حمل بيشتر بدليل عدم نياز به پشتيباني کرنل‬
‫تعويض متن سريعتر بين نخها‬
‫عدم استفاده از مزيت معماري چند پردازنده اي‬
‫‪Mach C-threads, BSD, Solaris UI-threads,DCE-threads‬‬
‫‪12‬‬
‫چند به يک‬
‫‪13‬‬
‫يک به يک‬
‫‪‬‬
‫‪ Pthreads‬بعنوان نخ سطح هسته در داخل هسته پياده سازي مي شود‪.‬‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫کتابخانه براي هر نخ سطح کاربر يک نخ سطح کرنل تقاضا مي کند‬
‫کتابخانه نخ ممکن است هنوز بطور گسترده با همگام سازي نخها درگير باشد اما‬
‫کرنل ايجاد و زمانبندي نخ را انجام مي دهد‬
‫تعداد نخها براي هر فرآيند بايد معلوم باشد‪.‬‬
‫مشخصات‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫معموال در تعويض متن نخها ُکند مي باشد چون نياز به مداخله کرنل دارد‪ .‬اين بدين‬
‫معني است که برنامه ها که مکررا نياز دارند تا براي همگام سازي بالک شوند‬
‫کندتر از ديگر مدلها اجرا خواهند شد‬
‫در يک فرايند از امکانات معماري چند پردازنده اي بطور کامل استفاده مي گردد‬
‫‪Windows,Linux‬‬
‫‪14‬‬
‫يک به يک‬
‫‪15‬‬
‫چند به چند‬
‫‪‬‬
‫سعي به ادغام مزيت مدلهاي يک به يک و چند به يک دارد‪.‬‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫نياز گسترده به هماهنگي بين کتابخانه نخ سطح کاربر و سطح کرنل دارد‪ .‬آنها در مسئوليت‬
‫زمانبندي شريک هستند‬
‫هر فرايند داراي مخزنی از نخهاي سطح کاربر است‪.‬‬
‫نخهاي سطح کاربر توسط کتابخانه سطح کاربر مديريت شده و آماده اجرا مي گردند‪.‬‬
‫کرنل يکي از نخهاي سطح کاربر را انتخاب کرده و به يکي از نخهاي سطح کرنل متعلق به‬
‫مجموعه نخهاي فرآيند نگاشت مي کند‪.‬‬
‫مشخصات‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫بيش از يک نخ سطح کاربر مي تواند به يک نخ سطح کرنل نگاشت شود‪.‬‬
‫در يک فرايند از امکانات معماري چند پردازنده اي بطور کامل استفاده مي گردد‬
‫بيشتر تعويض متن در حالت کاربر است‪ ،‬تعويض نخ هاي کاربر بدون تعويض نخهاي سطح‬
‫کرنل صورت مي گيرد‬
‫پيچيدگي زياد براي هماهنگ کردن کتابخانه سطح کاربر و هسته‬
‫‪Solaris, HP, AIX‬‬
‫‪16‬‬
‫چند به چند‬
‫‪17‬‬
‫انواع مدل هاي نخ کشي‬
Boss-worker
Peer-to-peer
pipeline
18



‫انواع مدل هاي نخ کشي‬
‫‪‬‬
‫‪Boss-worker‬‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫يک نخ(‪ )boss‬ساير نخها(‪ )worker‬را ايجاد نموده و به‬
‫هر کدام وظيفه اي را تخصيص مي دهد‪.‬‬
‫نخ ‪ worker‬وظيفه را اجرا نموده و در صورت نياز با‬
‫ساير نخها همگام مي شود‪.‬‬
‫نخ ‪ boss‬در يک حلقه مداوما رخدادها را دريافت کرده و‬
‫نخهايي براي اجراي وظايف ايجاد مي نمايد‪.‬‬
‫نخ ‪ boss‬مي تواند منتظر اجرا و خاتمه يک نخ بماند‪.‬‬
‫‪19‬‬
‫انواع مدل هاي نخ کشي‬
‫‪‬‬
‫‪Peer-to-peer‬‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫همه نخهاي وضعيت کاري يکسان دارند‬
‫يک نخ وظيفه ايجاد ساير نخها را دارد ولي خودش هم‬
‫‪ worker‬محسوب مي شود‪.‬‬
‫‪Pipeline‬‬
‫‪‬‬
‫‪‬‬
‫مانند خط مونتاژ‪:‬پردازش دنباله اي از اقالم در مراحل‬
‫مختلف‪.‬‬
‫براي هر مرحله يک نخ ورودي را دريافت کرده و آنرا‬
‫پردازش مي نمايد‪ .‬سپس نخ ديگر براي مرحله بعد پردازش‬
‫ديگري را روي ورودي‪20‬انجام مي دهد‪.‬‬
‫مدل نخ کشي ‪Pthread‬‬
‫‪‬‬
‫‪‬‬
‫نخ ها در يک فرآيند وجود دارند‪.‬‬
‫همه نخ ها ”همتا“(‪ )peer‬هستند‪:‬‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫مدل پدر‪-‬فرزند صريح نمي باشد‬
‫استثنا ‪ “main thread” :‬اطالعات فرآيند را نگه داري مي کند‬
‫‪Pthread API‬‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫مديريت نخ ها‪creating, detaching, joining,etc :‬‬
‫‪ :Mutex‬مربوط به همگام سازي مي باشد‪.‬‬
‫متغيرهاي شرطي‪ :‬ارتباط بين نخهايي که از ‪ mutex‬اشتراکي استفاده‬
‫مي کنند‬
‫‪21‬‬
‫‪main thread‬‬
‫‪‬‬
‫‪‬‬
‫نخ اوليه زماني ايجاد مي شود که تابع‬
‫بوسيله بارکننده فرآيند احضار گردد‪.‬‬
‫اگر ‪ main thread‬خاتمه يابد‪ ،‬فرايند خاتمه مي يابد حتي‬
‫اگر نخ هايي در حال اجرا وجود داشته باشد‪ ،‬مگر‬
‫اقدامات احتياطي در نظر گرفته شده باشد‪.‬‬
‫)(‪main‬‬
‫‪‬‬
‫براي اجتناب از خاتمه کامل نخ‪ ،‬از‬
‫مي گردد‪.‬‬
‫‪22‬‬
‫)(‪pthread_exit‬‬
‫در‬
‫‪C‬‬
‫استفاده‬
‫ايجاد نخ‬
pthread_create(
pthread_t *tid,
const pthread_attr_t *attr,
void *(*func)(void *),
void *arg);




tid - pointer to the identifier of the created thread
attr - thread attributes
func - pointer to the function the thread will execute
arg - the argument of the executed function (usually a struct)
23
‫ايجاد نخ‬
‫;)‪pthread_create(tid, attr, func, arg‬‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫زمانيکه تابع )(‪ func‬خاتمه يابد(‪ )return‬نخ هم به پايان مي‬
‫رسد‪.‬‬
‫مقدار بازگشتي ‪ pthread_create‬اگر صفر باشد يعني‬
‫اجرا موفق بوده و در صورتيکه ناموفق باشد عدد مثبتي به‬
‫عنوان شماره خطا بازگشت داده مي شود‪.‬‬
‫متغير ‪ errno‬مقدار دهي نمي گردد‪.‬‬
‫شناسه(‪ )ID‬نخ در ‪ tid‬بازگشت داده مي شود‪.‬‬
‫‪24‬‬
‫ايجاد نخ‬
‫;)‪pthread_create(tid, attr, func, arg‬‬
‫‪‬‬
‫خصيصه نخ که با ‪ attr‬مي توان مقداردهي کرد‪:‬‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫‪detached state‬‬
‫‪scheduling policy‬‬
‫در صورتيکه ‪ attr‬برابر ‪ NULL‬قرار دهيم‪ ،‬خصيصه‬
‫پيش فرض سيستم را به نخ خواهد داد‪.‬‬
‫‪25‬‬
‫پايان نخ‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫خاتمه روال اصلي براي ايجاد نخها‬
‫فراخواني زير روال ‪ pthread_exit‬در نخ‬
‫خاتمه يک نخ توسط نخ ديگر با روال ‪pthread_cancel‬‬
‫خاتمه فرآيند توسط روالهايي مانند ‪exit‬‬
‫‪26‬‬
#include <pthread.h>
#include <stdio.h>
#define NUM_THREADS
5
void *PrintHello(void *threadid)
{
long tid;
tid = (long)threadid;
printf("Hello World! It's me, thread #%ld!\n", tid);
pthread_exit(NULL);
}
int main (int argc, char *argv[])
{
pthread_t threads[NUM_THREADS];
int rc;
long t;
for(t=0; t<NUM_THREADS; t++){
printf("In main: creating thread %ld\n", t);
rc = pthread_create(&threads[t], NULL, PrintHello, (void *)t);
if (rc){
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
}
pthread_exit(NULL);
}
27
‫ارسال پارامتر به نخ‬
‫‪‬‬
‫امکان ارسال فقط يک پارامتر به نخ فراهم شده است‬
‫‪‬‬
‫‪‬‬
‫براي ارسال بيش از يک مقدار از ‪ struct‬استفاده مي شود‬
‫همه پارامترها بايد تبديل نوع به )* ‪ (void‬گردند‬
‫‪28‬‬
‫مثال – ارسال پارامتر به نخ‬
long *taskids[NUM_THREADS];
for(t=0; t<NUM_THREADS; t++)
{
taskids[t] = (long *) malloc(sizeof(long));
*taskids[t] = t;
printf("Creating thread %ld\n", t);
rc = pthread_create(&threads[t], NULL, PrintHello, (void *) taskids[t]);
...
}
int rc;
long t;
for(t=0; t<NUM_THREADS; t++)
{
printf("Creating thread %ld\n", t);
rc = pthread_create(&threads[t], NULL, PrintHello, (void *) &t);
...
}
29
‫الحاق(‪)joining‬‬
‫‪‬‬
‫‪‬‬
‫الحاق يکي از راههاي همگام کردن (‪)synchronization‬‬
‫دو نخ مي باشد‬
‫روال )(‪ pthread_join‬روال فراخواننده خود را مسدود‬
‫مي نمايد تا زمانيکه نخ مشخص شده(‪ )thraedid‬خاتمه‬
‫يابد‬
‫‪30‬‬
‫الحاق(‪)joining‬‬
‫‪‬‬
‫اطالع از وضعيت نخ خاتمه يافته(‪)status‬‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫بايد نخ با )(‪ pthread_exit‬خاتمه يافته باشد‪.‬‬
‫امکان الحاق چند نخ به يک نخ بطور همزمان وجود‬
‫ندارد‪.‬‬
‫دو روش همگام سازي ديگر‪:‬‬
‫‪Mutex , Condition Variable‬‬
‫‪31‬‬
‫‪‬‬
‫قابليت الحاق‬
‫‪‬‬
‫‪‬‬
‫زمانيکه يک نخ ايجاد مي شود‪ ،‬با مقداردهي يکي از خصايصش مي توان قابليت الحاق‬
‫نخ را تعريف کرد‪:‬‬
‫‪‬‬
‫‪Joinable or detached‬‬
‫قابل الحاق‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫منفصل‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫بطور پيش فرض نخها قابل الحاق شدن هستند‬
‫منابع تا زمانيکه الحاق رخ دهد حفظ مي شود‬
‫نمي توانند به نخي ملحق شوند‬
‫منابع در زمان خاتمه نخ آزاد مي شوند‬
‫عملکرد‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫تعريف يک متغير از نوع داده ‪pthread_attr_t‬‬
‫مقداردهي اوليه و پيش فرض متغير خصيصه با روال )(‪pathread_attr_init‬‬
‫مقدار دهي خصيصه با )(‪pathrad_attr_setdetachstate‬‬
‫آزادسازي منابع استفاده شده توسط خصيصه‪pthread_attr_destroy() :‬‬
‫‪32‬‬
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#define NUM_THREADS 4
void *BusyWork(void *t)
{
int i;
long tid;
double result=0.0;
tid = (long)t;
printf("Thread %ld starting...\n",tid);
for (i=0; i<1000000; i++)
{
result = result + sin(i) * tan(i);
}
printf("Thread %ld done. Result = %e\n",tid, result);
pthread_exit((void*) t);
}
33
int main (int argc, char *argv[])
{
pthread_t thread[NUM_THREADS];
pthread_attr_t attr;
int rc;
long t;
void *status;
/* Initialize and set thread attribute */
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
for(t=0; t<NUM_THREADS; t++) {
printf("Main: creating thread %ld\n", t);
rc = pthread_create(&thread[t], &attr, BusyWork, (void *)t);
if (rc) {
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
}
/* Free attribute and wait for the other threads */
pthread_attr_destroy(&attr);
for(t=0; t<NUM_THREADS; t++) {
rc = pthread_join(thread[t], &status);
if (rc) {
printf("ERROR; return code from pthread_join() is %d\n", rc);
exit(-1);
}
printf("Main: completed join with thread %ld having a status
of %ld\n",t,(long)status);
}
printf("Main: program completed. Exiting.\n");
pthread_exit(NULL);
}
34
‫ارتباط بين نخها‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫متغيرهاي سراسري‬
‫پارامترهاي ارسالي به نخ بهنگام ايجاد نخ‬
‫فايلها‬
‫مشکل ‪ :‬دسترسي همزمان به منابع‬
‫‪35‬‬
‫ارتباط بين نخها‬
‫‪36‬‬
‫روشهاي همگام سازي‬
‫‪‬‬
‫همگام سازي‬
‫‪‬‬
‫‪‬‬
‫ارتباط بين نخها از طريق به اشتراک گذاشتن منابع سخت‬
‫افزاري و نرم افزاري ممکن است که براي دسترسي به آنها‬
‫نياز به همگام سازي وجود دارد‪.‬‬
‫مکانيزم هاي همگام سازي‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫سمافور و ‪mutex‬‬
‫قفلهاي خواندن‪-‬نوشتن‬
‫متغيرهاي شرطي‬
‫‪37‬‬
‫‪Mutex‬‬
‫‪‬‬
‫منبع اشتراکي‪ :‬داده‬
‫‪‬‬
‫‪‬‬
‫با استفاده از متغيرهاي سراسري يا فايلها‬
‫مشکل‪ :‬شرايط رقابتي در دسترسي به ناحيه حافظه‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫ناحيه بحراني‪ :‬قطعه اي از کد که روي ناحيه مشترک تغييرات‬
‫ايجاد مي نمايد‬
‫راه حل‪ :‬انحصار متقابل در ناحيه بحراني‬
‫‪ :mutex‬سمافور دودويي براي جلوگيري از شرايط‬
‫رقابتي در ناحيه بحراني‬
‫‪38‬‬
‫‪Mutex‬‬
‫‪‬‬
‫توالي عمليات نمونه براي استفاده از ‪mutex‬‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫ايجاد و مقدار دهي اوليه ‪mutex‬‬
‫تالش چند نخ براي قفل کردن ‪mutex‬‬
‫موفق شدن فقط يک نخ و در اختيار گرفتن ‪mutex‬‬
‫اجراي تعدادي دستور توسط نخي که ‪ mutex‬را در اختيار‬
‫دارد‬
‫باز کردن قفل توسط نخي که ‪ mutex‬را در اختيار دارد‬
‫ساير نخها ‪ mutex‬را در اختيار گرفته و تکرار مراحل‬
‫فوق‬
‫آزادسازي ‪mutex‬‬
‫‪39‬‬
‫‪Mutex‬‬
‫‪‬‬
‫تعريف و مقداردهي اوليه ‪mutex‬‬
‫‪‬‬
‫‪‬‬
‫تعريف متغير از نوع ‪pthread_mutex_t‬‬
‫مقداردهي اوليه‬
‫‪‬‬
‫ايستا در زمان تعريف‬
‫;‪pthread_mutex_t mutex =PTHREAD_MUTEX_INITIALIZER‬‬
‫‪‬‬
‫پويا‪ ,‬با استفاده از روال )(‪pthread_mutex_init‬‬
‫‪‬‬
‫با استفاده از شيء خصيصه مي توان خصوصيات شيء ‪ mutex‬را نيز‬
‫تعريف نمود‪.‬‬
‫‪40‬‬
Mutex
‫آزاد سازي اشيا‬
‫ با استفاده از روال‬mutex ‫آزاد سازي شيء‬
pthread_mutex_destroy()
mutex ‫آزاد سازي شيء خصيصه‬
pthread_mutexattr_destroy()
41



‫‪Mutex‬‬
‫‪‬‬
‫قفل گذاري ‪mutex‬‬
‫‪‬‬
‫قفل با روال ‪:‬‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫در صورتيکه ‪ mutex‬قبال توسط نخي قفل شده باشد‪ ،‬نخ فراخواننده روال‬
‫بالک مي شود تا زمانيکه قفل ‪ mutex‬آزاد گردد‪.‬‬
‫قفل با روال ‪:‬‬
‫‪‬‬
‫)(‪pthread_mutex_lock‬‬
‫)(‪pthread_mutex_trylock‬‬
‫در صورتيکه ‪ mutex‬قبال توسط نخي قفل شده باشد‪ ،‬روال خاتمه سافته و‬
‫خطايي مبني بر ‪ busy‬بر مي گرداند(مناسب براي جلوگيري از ‪.)deadlock‬‬
‫بازکردن قفل ‪mutex‬‬
‫‪‬‬
‫فراخواني روال‬
‫کننده ‪mutex‬‬
‫)(‪ pthread_mutex_unlock‬توسط نخ قفل‬
‫‪42‬‬
typedef struct{
double
*a;
double
*b;
double
sum;
int
veclen;
}DOTDATA;
#define NUMTHRDS 4
#define VECLEN 100
DOTDATA dotstr;
pthread_t callThd[NUMTHRDS];
pthread_mutex_t mutexsum;
void *dotprod(void *arg)
{
int i, start, end, len ;
long offset;
double mysum, *x, *y;
offset = (long)arg;
len = dotstr.veclen;
start = offset*len;
end
= start + len;
x = dotstr.a;
y = dotstr.b;
mysum = 0;
for (i=start; i<end ; i++) {
mysum += (x[i] * y[i]);
}
pthread_mutex_lock (&mutexsum);
dotstr.sum += mysum;
pthread_mutex_unlock (&mutexsum);
pthread_exit((void*) 0);
}
43
int main (int argc, char *argv[])
{
long i;
double *a, *b;
void *status;
pthread_attr_t attr;
a = (double*) malloc (NUMTHRDS*VECLEN*sizeof(double));
b = (double*) malloc (NUMTHRDS*VECLEN*sizeof(double));
for (i=0; i<VECLEN*NUMTHRDS; i++){
a[i]=1.0;
b[i]=a[i];
}
dotstr.veclen = VECLEN;
dotstr.a = a;
dotstr.b = b;
dotstr.sum =0;
pthread_mutex_init(&mutexsum, NULL);
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
for(i=0; i<NUMTHRDS; i++){
pthread_create(&callThd[i], &attr, dotprod, (void *)i);
}
pthread_attr_destroy(&attr);
for(i=0; i<NUMTHRDS; i++)
pthread_join(callThd[i], &status);
printf ("Sum = %f \n", dotstr.sum);
free (a);
free (b);
pthread_mutex_destroy(&mutexsum);
pthread_exit(NULL);
}
44
‫قفلهاي خواندن‪ -‬نوشتن‬
‫‪‬‬
‫ورود چند نخ به ناحيه بحراني‬
‫‪‬‬
‫‪‬‬
‫در صورتيکه فقط عمل خواندن توسط نخها صورت پذيرد‬
‫در صورتيکه يک نخ عمل نوشتن را انجام دهد ساير نخها‬
‫نمي توانند وارد ناحيه بحراني گردند‪.‬‬
‫‪45‬‬
‫متغيرهاي شرطي‬
‫‪‬‬
‫امکان همگام سازي بر اساس مقادير داده‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫‪ mutex‬بر اساس دسترسي به داده همگام سازي مي نمود‬
‫‪Polling‬‬
‫متغيرهاي شرطي هميشه با يک ‪ mutex‬بکار مي‬
‫روند‬
‫‪46‬‬
‫متغيرهاي شرطي‬
‫‪‬‬
‫مراحل کار‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫تعريف و مقداردهي اوليه متغيرهاي سراسري‪ :‬در نخ اصلي‬
‫تعريف و مقدار دهي شيء متغيرهاي شرطي‪ :‬در نخ اصلي‬
‫تعريف و مقداردهي متغير ‪: mutex‬در نخ اصلي‬
‫ايجاد دو نخ ‪ A‬و ‪B‬‬
‫نخ ‪A‬‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫انجام کار تا حصول شرايط(رسيدن مقدار يک متغير‬
‫به مقدار مشخصي)‬
‫قفل کردن ‪ mutex‬و چک کردن متغير سراسري‬
‫فراخواني ‪ pthread_cond_wait‬براي بالک شدن‬
‫و انتظار يک سيگنال از نخ ‪( B‬بطور خودکار و‬
‫اتميک ‪ mutex‬باز شده ودر اختيار نخ ‪ B‬قرار مي‬
‫گيرد(‬
‫وقتي سيگنال دريافت شد‪ mutex ،‬بطور خودکار و‬
‫اتميک قفل مي شود‪.‬‬
‫باز کردن ‪ mutex‬بصورت صريح‬
‫ادامه‬
‫‪47‬‬
‫‪‬‬
‫نخ ‪B‬‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫قفل کردن ‪mutex‬‬
‫تغيير متغير سراسري که نخ ‪ A‬منتظر آن مي‬
‫باشد‬
‫چک کردن مقدار متغير سراسري انتظار نخ‬
‫‪ A‬و بمحض حصول شرايط ايجاد سيگنال به‬
‫نخ ‪A‬‬
‫باز کردن ‪mutex‬‬
‫ادامه‬
‫فضاي آدرسي نخ‬
‫‪‬‬
‫هر داده اي که آدرسش توسط يک نخ تعيين مي گردد‪،‬‬
‫در فرآيند براي همه نخها قابل دسترسي هست‪.‬‬
‫‪‬‬
‫‪‬‬
‫شامل متغيرهاي ايستا‪ ،‬متغيرهاي خودکار و حافظه هاي‬
‫تخصيصي با ‪malloc‬‬
‫اين بدين معنا نيست که هر نخ نمي تواند داده اختصاصي‬
‫داشته باشد‪.‬‬
‫‪48‬‬