You are on page 1of 9

Nghin cu v :Thread, Semaphore, Mutex and Condition variable

TuongBV FPT Software


1,THREAD :
Bit cch lp trnh vi thread v multithread l mt trong nhng k nng cn thit ca mt
programmer tt. Trong bi vit ny s cp v POSIX (Portable Operating System Interface)
threads. Nh bn bit POSIX (chnh xc hn l chun IEEE 1003.1c ca t chc IEEE a
ra) bao gm nhng nh ngha giao din chung cho cc h iu hnh. iu c ngha l
nhng h iu hnh no support POSIX (GNU/Linux, BSD, Sun Solaris, Unix, ) th u c
nhng system call c prototype ging nh trong ti liu v POSIX a ra, mc d i vi mi
h iu hnh c cch implement khc nhau. POSIX threads (Pthreads) l mt cch rt tt
lm tng tin cy v performance cho chng trnh.
Threads cng tng t nh processes, u c phn chia thi gian bi kernel. Vi h thng
ch c mt b vi x l th kernel s dng cch phn chia thi gian lm cho cc threads
nh l chy ng thi theo cng cch thc kernel thc hin vi processes. V vi cc h
thng a nhn th cc threads thc s c th chay ng thi ging nh l nhiu processes.
Th th ti sao multithread li c a chung hn l nhiu process c lp i vi cc task c
mi quan h vi nhau? l bi v cc threads s dng chung cng mt khng gian b nh.
Mi thread c lp u c th truy nhp vo cng mt bin ton cc trong b nh. Trong khi
fork() cho php to ra nhiu process nhng rt kh khn trong vic trao i thng tin gia
process vi nhau v mi process c mt khng gian vng nh ring. Khng c mt cu tr li
n gin cho vic trao i gia cc process (IPC). Do vy m multiprocess programming s
phi chu 2 tr ngi ln:
- Perforamance thp v khi to mt process mi i hi kernel thc thi nhiu php tnh ton
cp pht b nh.
- Trong hu ht cc trng hp th IPC lm chng trnh tr nn phc tp hn rt nhiu.
Hn th na, qu ti v s phc tp khng phi l nhng th tt. Nu bn tng phi lm
nhng thay i ln cho mt chng trnh ca bn m support IPC, s rt tt nu s dng
cch tip cn chia s vng nh n gin ca threads. Pthreads khng cn phi nhng li gi
expensive v phc tp bi v threads sng cng mt ngi nh. Bn khng phi y d liu
thng qua mt file hoc mt vng nh no . Chnh v l do ny m bn nn cn nhc m
hnh mt process/nhiu threads hn l nhiu process/mt thread.
Nh ni trn, to mt thread nhanh hn rt nhiu (t 10 cho n 100 ln) so vi to mt
process. Kernel khng cn phi to mt bn copy c lp ca khng gian b nh hin thi,
bng cc m t file (file descriptors). iu tit kim rt nhiu thi gian ca CPU. Chng ta
s xem xt mt v d.

==============================================================================
C Code for fork() creation test
==============================================================================

#define NFORKS 50000


void do_nothing()
{
int i;
i= 0;
}
main()
{
int pid, j, status;
for (j=0; j<NFORKS; j++) {
/*** error handling ***/
if ((pid = fork()) < 0 ) {
printf ("fork failed with error code= %d\n", pid);
exit(0);
}
/*** this is the child of the fork ***/
else if (pid ==0) {
do_nothing();
exit(0);
}
/*** this is the parent of the fork ***/
else {
waitpid(pid, status, 0);
}
}

==============================================================================
C Code for pthread_create() test
==============================================================================
#include <pthread.h>
#define NTHREADS 50000
void *do_nothing(void *null)
{
int i;
i=0;
pthread_exit(NULL);
}
main()
{
int rc, i, j, detachstate;
pthread_t tid;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);

for (j=0; j<NTHREADS; j++) {


rc = pthread_create(&tid, &attr, do_nothing, NULL);
if (rc) {
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}

/* Wait for the thread */


rc = pthread_join(tid, NULL);
if (rc) {
printf("ERROR; return code from pthread_join() is %d\n", rc);
exit(-1);
}

pthread_attr_destroy(&attr);
pthread_exit(NULL);

Tuy nhin th multithread cng c im yu nht nh. chnh l kh nng v ca n. Bi v


cc threads trong cng mt khng gian b nh nn nu mt thread v (crash) s ko theo
ton b process v cc thread khc b terminate. Tri li th khi mt process b v th khng
nh hng g n cc process khc. Chnh v vy nhng h thng ln th h li s dng cc
daemon l multiprocess hn l multithread.
Note: Trong phn ny chng ta ch n 2 lnh:
rc = pthread_create(&tid, &attr, do_nothing, NULL);

y l to mt Thread v n s goto function do_nothing rc return 0 nu thnh cng


rc = pthread_join(tid, NULL);
wait cho thread ny hot ng xong hon thnh th rc = 0;
Note for a simple code
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
int myglobal;
void *thread_function(void *arg) {
int i,j;
for ( i=0; i<20; i++ ) {
j=myglobal;
j=j+1;
printf(".");
fflush(stdout);
sleep(1);
myglobal=j;
}
return NULL;
}
int main(void) {
pthread_t mythread;
int i;

if ( pthread_create( &mythread, NULL, thread_function, NULL) ) {


printf("error creating thread.");
abort();
}
for ( i=0; i<20; i++) {
myglobal=myglobal+1;
printf("o");
fflush(stdout);
sleep(1);
}
if ( pthread_join ( mythread, NULL ) ) {
printf("error joining thread.");
abort();
}
printf("\nmyglobal equals %d\n",myglobal);
exit(0);
}

/*Hy suy ngh khi chy chng trnh ny v on xem bin : myglobal s c gi tr l bao
nhiu v ti sao.y l mt li nn chng ta phi control n v chng ta s dng Mutexs cho vn
ny */
2,MUTEX:
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
int myglobal;
pthread_mutex_t mymutex=PTHREAD_MUTEX_INITIALIZER;
void *thread_function(void *arg)
{
int i,j;
for ( i=0; i<20; i++ ) {
pthread_mutex_lock(&mymutex);
j=myglobal;
j=j+1;
printf(".");
fflush(stdout);
sleep(1);
myglobal=j;
pthread_mutex_unlock(&mymutex);
}
return NULL;
}
int main(void)
{
pthread_t mythread;
int i;
if ( pthread_create( &mythread, NULL, thread_function, NULL) ) {
printf("error creating thread.");

abort();
}
for ( i=0; i<20; i++) {
pthread_mutex_lock(&mymutex);
myglobal=myglobal+1;
pthread_mutex_unlock(&mymutex);
printf("o");
fflush(stdout);
sleep(1);
}
if ( pthread_join ( mythread, NULL ) ) {
printf("error joining thread.");
abort();
}
printf("\nmyglobal equals %d\n",myglobal);
exit(0);
}
Nu chng ta so snh on m ny vi on m trong chng trnh thread2.c, chng ta s thy
c thm nhng li gi hm pthread_mutex_lock() v pthread_mutex_unlock(). Nhng li gi hm
ny rt cn thit trong lp trnh vi thread. Chng cung cp cch thc loi tr ln nhau (mutual
exclusion) c ngha l khi mt thread s dng ti nguyn th thread khc khng c s dng
v phi ch cho n khi thread kia gii phng ti nguyn. Khng c hai thread no c th cng
c mt mutex b kha mt thi im.
chnh l cch thc mutex lm vic. Nu thread a c gng kha mt mutex trong khi thread
b kha cng mutex ri th thread a s ri vo trng thi ng (sleep). Ngay khi thread b
gii phng mutex (thng qua pthread_mutex_unlock()), thread a s c th kha mutex (ni mt
cch khc th khi gi tr ca hm pthread_mutex_lock() s c tr v vi mutex b lock).
Ngc li, nu thread c c gng kha mutex trong khi thread a ang nm gi n th thread c
cng s b ri vo trng thi ng tm thi. Tt c thread m cng ri vo trng thi ng t lnh
gi pthread_mutex_lock() v mt kha mutex b lock sn ri s c a vo hng i truy
nhp vo mutex.
pthread_mutex_lock() v pthread_mutex_unlock() thng c s dng bo v cu trc d
liu. N m bo rng ch c mt thread ti mt thi im c th truy nhp vo cu trc d liu
bng vic kha v m kha. Bn cng c th on ra rng POSIX threads s cp mt kha m
khng a thread vo trng thi ng khi n c gng kha mt mutex khng b kha.
Th nhng ti sao chng ta li phi a cc thread vo trng thi sleep? R rng n khng phi
l u im chnh ca thread khi m ta mun tn dng kh nng lm vic c lp v ng thi
ca cc thread? ng vy. Tuy nhin th cc chng trnh s dng thread vn thng cn phi
s dng mutex.
Nu bn nhn vo hm thread_function(), bn s nhn ra rng mutex b kha vo lc u vng
lp v gii phng khi kt thc. Trong v d ny th mymutex c dng bo v gi tr ca
myglobal. Nu nhn cn thn hn, s thy rng on m tng gi tr ca myglobal trong
thread_function s copy gi tr myglobal v mt bin local v ghi tr li t local vo myglobal sau
khi tng (on m sleep mt giy c th b i. Chng c l do g thread_function phi sleep
khi s dng mutex. N c thm vo c th nhn r hn s khc bit).

3, CONDITION VARIABLE:
Chng ta bit cch thc dng mutex ng b ha gia cc thread, trnh xung
t gia cc thread khi cng truy cp ti nguyn. Tuy nhin th khng phi mutex

lm c tt c. V d nh chng ta s lm th no nu chng ta mun thread i


mt iu kin no xy ra vi d liu trong vng chia s? Chc chn l chng ta s
lm bng cch lp lin tc vic kha v m kha mutex ( m bo ng b gia
cc thread cng truy nhp vo vng d liu chia s) v kim tra bt c s thay i
no trn d liu. Cng lc s rt nhanh chng thread s m kha mutex cho cc
thread khc c th thc hin s thay i trn vng d liu . Nh vy th cch tip
cn ny tht kinh khng bi v chng ta s cn mt vng lp busy-loop nhn ra s
thay i vng d liu. N tht l lng ph CPU. (Bn cn phi phn bit gia mt
chng trnh trng thi idle v busy!!!).
Chng ta c th cho thread ng mt cht, v d 3 giy chng hn gia mi
mt ln kim tra, nhng r rng n khng ti u tuyt i. Ci chng ta cn l phi
a thread vo trng thi ng cho n khi mt iu kin no c tha mn.
Mt khi iu kin c tha mn th n s nh thc thread ca chng ta n tip
tc s l. chnh l mt kiu c ch bo hiu (signal). Khi c tn hiu th thread
mi c nh thc s l tn hiu .
Trong bi ny chng ta s s dng bin pthread_condition_t th hin cch thc
bo hiu ny. Bin pthread_condition_t c cch s dng cng tng t nh bin
mutex. Chng ta khai bo v khi to nh sau:
pthread_cond_t condition = PTHREAD_COND_INITIALIZER;
hoc s dng
int pthread_cond_init(pthread_cond_t *cond, pthread_cond_attr_t
*cond_attr);
Nhiu thread c th thc hin vic ch trn cng mt bin iu kin. Khi mt thread
no mun bo hiu vic thay i cho cc thread ang ch th n s pht tn hiu
n bin iu kin . Khi th cc thread ang ch trn bin iu kin s thot
khi trng thi ng. pht tn hiu n bin iu kin chng ta dng
int pthread_cond_signal(pthread_cond_t *cond);
int pthread_cond_broadcast(pthread_cond_t *cond);
pthread_cond_broadcast gi tn hiu kiu broadcast s nh thc ton b cc thread
ang ch.
ch mt bin iu kin, chng ta hy vng mt hm pthread_cond_wait() chp
nhn mt bin pthread_cond_t lm tham s. Khi hm pthread_cond_wait c gi
n s ri vo trng thi ng cho ti khi bin iu kin c nh thc v nh thc
n. Khi n c nh thc l lc hm pthread_cond_wait tr v. Mt vn quan
trng l bin iu kin cng phi ng b ha, ngha l khi mt thread ang ch trn
bin iu kin cond th cc thread khc khng c thay i thuc tnh, hay hy bin
iu kin . Th nhng bn thn bin iu kin pthread_cond_t li khng cung cp
c ch ny nn thng chng ta s phi s dng chung vi mt bin mutex.
u tin chng ta kha mutex vic ch i trn bin iu kin l ng b
int rc = pthread_mutex_lock(&a_mutex);

Sau khi kha mutex chng ta s gi


rc = pthread_cond_wait(&a_cond, &a_mutex);

thc hin vic ch i trn bin iu kin


int pthread_cond_wait(pthread_cond_t* , pthread_mutex_t* );
int pthread_cond_timewait(pthread_cond_t* , pthread_mutex_t* ,
timespec);
Vic u tin pthread_cond_wait() lm gn nh ng thi l unlock bin mutex
a_mutex (do cc thread khc c thay i vng d liu ch i) v ch i trn
bin iu kin (do pthread_cond_wait() s thc dy khi n c bo hiu bi
thread khc). By gi th a_mutex b unlock v cc thread khc c th thay i
vng nh d liu ang theo di.
Lc ny th pthread_cond_wait() vn cha tr v. Vic unlock mutex sy ra ngay lp
tc nhng vic ch i trn bin iu kin a_cond th s block thread ca chng ta,
c ngha l thread s sleep v khng tiu tn mt chu k my CPU no cho n
khi n thc dy. Nhn t pha thread th n n gin ch l ch i hm
pthread_cond_wait() tr v. Khi pthread_cond_wait() tr v chnh l lc thread
thc gic v x l tip tc cc lnh tip theo thread sau pthread_cond_wait().
Gi s c mt thread khc l thread 2 lm nhim v lock a_mutex sau thay i
d liu trn mt bin a no , unlock a_mutex ri gi tn hiu bo hiu bin a
thay i n bin iu kin a_cond bng pthread_cond_signal(&a_cond). Ngay khi
thread 1 trn gi pthread_cond_wait(&a_cond, &a_mutex) th n s unlock
a_mutex, do lc ny th thread 2 bt u bc vo thc hin. Thread 2 s kha
mutex thnh cng, thay i trn bin a, unlock v gi tn hiu n bin a_cond.
Lc ny thread 1 ang b blocking, hm pthread_cond_wait cha tr v. Ngay khi
thread 2 gi tn hiu n a_cond th n s nh thc thread 1 v hm
pthread_cond_wait tr v. Ch rng ngay khi pthread_cond_wait tr v th n cng
ngay lp tc kha li bin mutex. N s x l tn hiu v chng ta s unlock sau khi
x l xong thread 1.
Tm li cc bc ch i mt bin iu kin din ra nh sau.
int rc = pthread_mutex_lock(&a_mutex);
rc = pthread_cond_wait(&a_cond, &a_mutex);
if (rc == 0) {
// Do something
}
pthread_mutex_unlock(&a_mutex);
Vy l chng ta sn sng vit nhng chng trnh multithread tht hay. Hy suy
ngh v bi tp sau m ti s th hin n trong cc bi tip theo:
Bn c n threads v m jobs. Bn mun rng chng ta lm n jobs trn n threads .
Mi khi c mt job n th bn s cp mt thread cho job .

4,SEMAPHORE:
/*on code v semaphore vi chc nng tng gim semaphore*/
/* Includes */
#include <unistd.h>
/* Symbolic Constants */
#include <sys/types.h> /* Primitive System Data Types */
#include <errno.h>
/* Errors */
#include <stdio.h>
/* Input/Output */
#include <stdlib.h>
/* General Utilities */
#include <pthread.h>
/* POSIX Threads */
#include <string.h>
/* String handling */
#include <semaphore.h> /* Semaphore */
/* prototype for thread routine */
void handler ( void *ptr );
/* global vars */
/* semaphores are declared global so they can be accessed
in main() and in thread routine,
here, the semaphore is used as a mutex */
sem_t mutex;
int counter; /* shared variable */
int main()
{
int i[2];
pthread_t thread_a;
pthread_t thread_b;
i[0] = 0; /* argument to threads */
i[1] = 1;
sem_init(&mutex, 0, 1);
semaphore */

/* initialize mutex to 1 - binary


/* second param = 0 - semaphore is

local */

/* Note: you can check if thread has been successfully created by


checking return value of
pthread_create */
pthread_create (&thread_a, NULL, (void *) &handler, (void *) &i[0]);
pthread_create (&thread_b, NULL, (void *) &handler, (void *) &i[1]);
pthread_join(thread_a, NULL);
pthread_join(thread_b, NULL);
sem_destroy(&mutex); /* destroy semaphore */
/* exit */
exit(0);
} /* main() */
void handler ( void *ptr )
{
int x;
x = *((int *) ptr);
printf("Thread %d: Waiting to enter critical region...\n", x);

sem_wait(&mutex);
/* down semaphore */
/* START CRITICAL REGION */
printf("Thread %d: Now in critical region...\n", x);
printf("Thread %d: Counter Value: %d\n", x, counter);
printf("Thread %d: Incrementing Counter...\n", x);
counter++;
printf("Thread %d: New Counter Value: %d\n", x, counter);
printf("Thread %d: Exiting critical region...\n", x);
/* END CRITICAL REGION */
sem_post(&mutex);
/* up semaphore */
pthread_exit(0); /* exit thread */
}

Note: Semaphore trong v d trn th u tin chng ta init semaphore


sem_init(&mutex, 0, 1);
trong ham init thi second parameter =0; cho semaphore l bin local cho mt chng
trnh v khc 0 th cho nhiu x l.thirth parameter l cho php c gi bao nhiu
thread trong qu trnh thc hin semaphore mi ln thc hin th hm sem_wait();
gim semaphore xung

Trong hm handler ():


+ sem_wait(&mutex): chc nng gim semaphore
+ sem_pos(&mutex): chc nng tng semaphore

You might also like