Thread

**Thread** нь CPU ашиглалтын суурь нэг нэгж нь юм. Энэ нь Thread ID, Program counter, регистерүүд, болон стак-аас бүрддэг. Thread нь мөн адилхан процессд хуваарьлагдсан Thread –үүдтэйгээ код-ын хэсгээ, өгөгдлийн хэсэг ба бусад үйлдлийн системын нөөцүүдийг(Жишээ нь: Файлыг нээх болон сигнал) дундаа хэрэглэн ажилладаг. Уламжлалт процесс нь удирдлагын ганц  thread-ээс бүрддэг. Tf процесс нь олон тооны удирдлагын thread –ээс бүрддэг бөгөөд энэ нь нэгээс илүү үйлдлийг тухайн мөчид гүйцэтгэж чаддаг. Зураг 4.1д уламжлалт 1 thread-тэй процесс болон олон thread бүхий процессын ялгааг харуулав. 

Санаа
	
Орчин үеийн desktop  PC –н дээр ажиллаж байгаа олон програм хангамжийн багц нь олон thread –тэй.  Аппликэйшн нь ихэвчилэн тусдаа процессууд хэд хэдэн удирлагын thread –ээс бүрдсэн хэлбэртэй хэвшүүлэгдсэн байдаг. Вэб хөтчөөр жишээ авбал үүний нэг thread нь текст эсвэл зургыг дэлгэцэн дээр харуулах харин тэр үед нөгөө thread нь сүлжээнээс өгөгдлийг хүлээн авдаг байж болно. Үгийг харуулж буй процесс нь график дүрсийг харуулж байгаа нэг процесс өөр ба хэрэглэгчийн оруулсан товчлуур дарагдах үед хариу өгөх нэг thread мөн 3 дахь thread  нь үсэглэлт болон дүрмийн алдааг шалгах шалгалтыг цаана нь явуулах бүтэцтэй бас байж болно.

## Ерөнхий ойлголт
Thread нь CPU ашиглалтын суурь нэг нэгж нь юм. Энэ нь Thread ID, Program counter, регистерүүд, болон стак-аас бүрддэг. Thread нь мөн адилхан процессд хуваарьлагдсан Thread –үүдтэйгээ код-ын хэсгээ, өгөгдлийн хэсэг ба бусад үйлдлийн системын нөөцүүдийг(Жишээ нь: Файлыг нээх болон сигнал) дундаа хэрэглэн ажилладаг. Уламжлалт процесс нь удирдлагын ганц  thread-ээс бүрддэг. Tf процесс нь олон тооны удирдлагын thread –ээс бүрддэг бөгөөд энэ нь нэгээс илүү үйлдлийг тухайн мөчид гүйцэтгэж чаддаг. Зураг 4.1д уламжлалт 1 thread-тэй процесс болон олон thread бүхий процессын ялгааг харуулав. 

Орчин үеийн desktop  PC –н дээр ажиллаж байгаа олон програм хангамжийн багц нь олон thread –тэй.  Аппликэйшн нь ихэвчилэн тусдаа процессууд хэд хэдэн удирлагын thread –ээс бүрдсэн хэлбэртэй хэвшүүлэгдсэн байдаг. Вэб хөтчөөр жишээ авбал үүний нэг thread нь текст эсвэл зургыг дэлгэцэн дээр харуулах харин тэр үед нөгөө thread нь сүлжээнээс өгөгдлийг хүлээн авдаг байж болно. Үгийг харуулж буй процесс нь график дүрсийг харуулж байгаа нэг процесс өөр ба хэрэглэгчийн оруулсан товчлуур дарагдах үед хариу өгөх нэг thread мөн 3 дахь thread  нь үсэглэлт болон дүрмийн алдааг шалгах шалгалтыг цаана нь явуулах бүтэцтэй бас байж болно.

Тодорхой нөхцөл байдлуудад нэг аппликэйшн нэг ажлыг хэд хэдэн удаа гүйцэтгэх шаардлагатай байж болно. Жишээ нь: Вэб сэрвэр нь хэрэглэгчийн web хуудас, зурагнууд, дуу, гэх мэт зүйлүүдийг үзэхийг хүссэн хүсэлтэнд зөвшөөрөх гэх мэт. Завгүй вэб сервэрүүд нь магад хэд хэдэн хэрэглэгчид зэрэг үүнлүү хандаж байж болно. Хэрэв энэ үед вэб сервер нь уламжлалт нэг thread-тэй процесс ашиглаж байвал энэ нь тухайн агшинд зөвхөн нэг л хэрэглэчид үйлчилж чадна. Бусад хэрэглэгчдийн хүсэлтийнхээ үйлчилгээг авах хугацаа үүнээс хамаараад маш их байж болно. 

Нэг шийдэх арга нь тусдаа нэг зөвхөн хүсэлт авдаг процесс сервер дээр байлгах шийдэл байна. Хэрэв сервер нь хүсэлт хүлээн авсан тохиолдолд, сервер нь энэ хүсэлтэд тусдаа бие даасан процесс бий болгож байна гэсэн үг. Үнэндээ энэ процесс үүсгэлт нь Thread түгээмэл хэрэглэгдэж эхлэхээс өмнө нийтлэг байсан зүйл. Процесс бий болгох нь  хугацаа зарцуулалт болон нөөц хэрэглэлтийн хувьд өндөр. Хэрэв шинэ процесс нь өмнө нь байсан процесс-тойгоо адил зүйлийг хийдэг бол яагаад заавал энэ бүх тогтмол зардалыг (нөөц , хугацаа) байлгах хэрэгтэй гэж? Үүнээс нэг процесс нь олон thread ашигладаг бол илүү үр дүнтэй, ашигтай гэсэн ойлголт гарч ирсэн. Энэ хандлага нь вэб серверийн процессыг мультитрэйд болгоно.  Сервер нь тусдаа хэрэглэгчийн хүсэлтүүдийг сонгох thread –ыг бий болгох ба хэрэв хүсэлт хийгдсэн тохиолдолд өөр процесс үүсгэж байснаас илүүтэйгээр сервер нь энэ хүсэлтэд үйлчлэх шинэ thread бий болгоно гэсэн үг.

Thread нь мөн зайн дуудлагын техникт (Remote procedure call (**RPC**)-д чухал үүрэгтэй. RPC нь дотоод процессуудын харилцааг бий болгох боломжийг энгийн функц эсвэл горимын дуудлагуудтай адил харилцааны механизмын тусламжтай хангадаг.

Ерөнхийдөө RPC серверүүд нь multithread байдаг. Хэрэв сервер нь мессеж хүлээн авсан тохиолдолд энэ нь мессежүүдэд тусдаа thread үүсгэн үйлчилдэг. Энэ нь серверийг хэд хэдэн хүсэлтэд нэгэн зэрэг үйлчлэх боломжийг олгодог. JAVA RMI систем нь бас төстэй ажилладаг. 

Эцэст нь олон үйлдлийн системүүдийн кернелүүд нь одоо multithread хэлбэртэй болсон. Хэд хэдэн thread –үүд нь kernel-д үйл ажиллагаагаа явуулдаг ба thread болгон тодорхой үйлдлийг гүйцэтгэж байдаг. Жишээ нь төхөөрөмжийн зохицуулалт болон тасалдлын зохицуулалт зэрэг. Жишээ нь : Solaris нь тодорхой хүрээний thread –үүдийг тасалдлыг зохицуулахад бий болгодог. Linux нь системийн чөлөөтэй санах ойг удирдахын тулд кернел thread –ын хэрэглэдэг. 

### Ашиг тус
            Multithread бүхий програмчлалыг ашигласнаар бий болох давуу талыг 4 том  ангилалуудад хувааж болдог.  

 **1. Хариу үйлдэл.** Multithread-ыг зохицож ажиллах програмд ашигласнаар энэ нь программын нэг хэсэг нь блоклогдсон эсвэл ямар нэгэн урт үйлдлийг гүйцэтгэж байвал үргэлжлүүлэн ажиллуулах боломжийг олгодог. Ингэснээр хэрэглэчид үзүүлэх хариу үйдлийг хурдасгаж байна. Жишээ нь: Multithread бүхий web browser нь хэрэглэгчийн харилцан үйлчлэлийг нэг thread биелүүлж байх үед зураг нь өөр thread –д хуулагдаж байх боломжийг олгож чадна.

**2.   Нөөц хуваарилалт.** Default үедээ, thread –үүд нь санах ой болон нөөцөө аль процессд хуваарилагдсан түүнтэйгээ хуваан дундаа хэрэглэдэг. Код болон өгөгдлийг хуваалцаж дундаа хэрэглэхийн ашигтай тал нь аппликэйшныг хэд хэдэн Thread үүдийг үйл ажиллагаагаа адилхан хаягын зайнд биелүүлэх боломжийг олгодог.

**3.   Хэмнэлт.**  Санах ой болон нөөц ашиглалтыг бодож үзвэл олон тооны процессыг даах чадвартай PC –тэй байхын тулд мөнгө өртөг их үрэх шаардлагатай болно. Thread –ын хувьд энэ нь зөвхөн аль процессд хуваарилагдсан байна тэр процесстойгоо нөөцөө хуваан эзэмшдэг.Thread үүсгэх болон хооронд нь шилжих нь илүү хэмнэлттэй.  Нэмэлт зардлуудыг хооронд ялгааг тийм их байхгүй ч процесс бий болгох үйл явц нь thread үүсгэснээс илүү тэй цаг үрсэн асуудал. Жишээ нь : Solaris –ын хувьд Процесс үүсгэх нь thread үүсгэснээс 30 хувь удаан байдаг. Утга солилцох нь ойролцоогоор 5 дахин удаан байдаг.

**4.   Multi процессор архитектурын хэрэглээ.** Multithread-ын давуу тал тухайн хэрэглэж байгаа систем нь Multiprocessor архитектуртай бол үүний бүтээмж илүү ихэснэ. Процессууд дээр паралеллаар thread үүд нь зэрэг ажиллаж болох болохоор ийм боломжийг олгодог. 1 thread –тэй процесс нь CPU-ны тооноос үл хамааран зөвхөн нэг CPU н дээр ачааллагдаж чадна. Олон CPU-тэй системд Multi-Thread хэрэглэх нь бүтээмжийг ихэсгэнэ. 

### Multi-Thread моделууд
Бидний одоог хүртэл Thread –ын ярилцсан сэдэв нь ерөнхий ойлголтуудыг зөвхөн ярьсан. Гэвч thread –ын дэмжлэгийн түвшин хэрэглэгчийн түвшинд буюу хэрэглэгчийн thread аль эсвэл кернел-ийн дэмжлэг буюу кернел thread гэж байдаг. Хэрэглэгчийн кернел нь кернелийн дээд түвшинд дэмжигдэж ажилладаг ба кернелийн тусламжгүй удирдагдаж байдаг бол Кернел thread нь шууд үйлдлийн системээр удирдагдаж байдаг. Өнөө үеийн үйлдлийн системүүд болох Windows XP, Linux, Mac OS X, Solaris болон Tru64 UNIX(хуучраан Digital UNIX) гэх мэт үйлдлийн системүүд нь кернел thread –үүдийн дэмжин ажилладаг.

Эцсийн дүнд хэрэглэгчийн кернел thread болн кернелийн thread –ын хооронд харилцаа заавал байх ёстойг анхаарах хэрэгтэй. Энэ хэсэгт бид энэ холбоог тогтоож болох нийтлэг 3 аргуудаас үзнэ.

### Олноос нэгрүү модел
Олноос нэгрүү моделд (Зураг 4,2)   олон хэрэглэгчийн түвшиний thread –үүд нэг кернелрүү гэсэн зураглалыг харуулсан байна. Thread удирдлага нь хэрэглийн хэсэгт байгаа сангаар удирдагдана. Тийм учраас энэ нь үр дүнтэй; Гэвч хэрэв thread блок хийх үйлдэл гүйцэтгэвэл процесс бүхэлдээ блоклогдоно .

Мөн тухайн агшинд зөвхөн нэг л thread кернелрүү хандалт хийж чадна, олон thread –үүд multiprocess –ын үед паралелль-аар зэрэг гүйцэтгэгдэж чадахгүй.  Green threads – Solaris-д энэ моделыг хэрэглэдэг ийм сан идэвхитэй байдаг. GNU-ын хувьд Portable threads.

### 1-ээс 1 рүү модел
Зураг 4.3т хэрэглэгчийн thread болгон кернел thread тэй холбогдосон байгааг харж болж байна. Энэ нь илүү зэрэг гүйцэтгэх боложийг нэг thread нь блок үйлдлийг гүйцэтгэж байхад нөгөө thread гүйцэгтэх боломжтой учир өмнөх олноос нэгрүү гэсэн моделыг бодвол олгож байна. Энэ нь мөн Multiprocessor үед thread –үүдийг параллелиар ажиллах боломжийг олгож байна. 

Энэ моделын нэг дутагдалтай гэж хэлж болохор тал нь хэрэглэгчийн thread үүсэхдээ заавал кернелийн thread тэй харгалзаж байх ёстой. Яагаад гээвэл кернелийн thread үүсгэх нь програмын ажиллагаанд ачаалал үүсгэх боломжтой. Ихэнхидээ энэ моделыг суурьлуулахдаа үйлдлийн систем дэмжиж байгаа thread үүдээр хязгаарлагддаг. Linux болон Windows үйлдлийн системүүд нь энэ нэгээс нэг моделыг хэрэгжүүлдэг.

## Олноос олон модел
Зураг 4.4 дээр олон хэрэглэгчийн түвшиний thread –үүдийг  жижиглэн эсвэл кернелийн thread –үүдийн тоотой адил болгож мультиплекс хийж байна. Кернелийн thread –үүдийн тоонууд нь тодорхой програм болон тодорхой системийн хувьд тодорхойлон заагдсан байж болдог. Програм нь магадгүй multiprocessor үед uniprocess үеэсээ илүү олон kernel thread болгон хуваарилагдсан байж болно. Олноос нэгрүү гэсэн модел нь хөгжүүлэгчийг өөрийн хүссэнэээрээ хэдэн ч хэрэлэгчийн thread үүсгэж болж байсан ба энэ үед жинхэнэ зэрэг ажиллагаа биелэгдээгүй. Учир нь Кернел нь тухайн агшинд нэгхэн thread хуваарилаж чадна. Харин нэгээс нэг гэсэн модел нь илүү зэрэг ажиллаж боломжийг бий болгодог боловч хөгжүүлэгч хэтэрхий их thread програмд үүсгэхгүй байх тал дээр анхаарах ёстой (магадгүй зарим тохиолдолд хэдийг бий болгож тал дээр хязгаар байдаг). Олноос олон модел нь эдгээр сул талуудын алийг нь ч агуулаагүй ба хөгжүүлэгч нь шаардлагатай хэдэн ч хэрэглэгийн thread үүсгэж болно нэмээд холбоотой thread kernel нь multiprocessor-т паралеллиар ажиллаж чадна. Үүнчлэн thread нь блок систем үйлдэл хийсэн тохиолдолд кернел нь өөр thread –ийг ажиллахаар хуваарилаж чадна.

Мөн хэрэглэгчийн түвшиний thread үүдийг кернелрүү multiplex хийдэг энэ нөхцөлийг хааяаа 2 түвшинт модел гэж тодорхойлж болдог ба үйлдлийн системээр дэмжигддэг IRIX, HP-UX мөн TRU64 UNIX гэх мэт. Solaris нь Solaris –өөс өмнөх үеүүдэд 2 түвшинд дэмждэг. Гэвч Solaris 9өөс эхлэн үйлдлийн систем нь 1-ээс 1 моделыг ашигладаг болсон. 

### Thread сангууд
Thread сан нь програмчид thread –ыг үүсгэх болон удирдахад зориулсан API –аар хангадаг. Thread сан суурьшуулах 2 гол замууд байдаг. Эхний арга зам нь санг хэрэглэгчийн зайд ямар ч кернелийн дэмжлэггүй олгох. Бүх код болон өгөгдлийн бүтэц нь хэрэглэгчийн хэсэгт байгаа санд зориулагдсан. Энэ нь юу гэсэн үг гэхээр сангаас функц дуудах нь хэрэглэгийн хэсгээс дотоод функц дуудна гэсэн үг тэгэхээр системээс дуудалт хийхгүй гэсэн үг.

2 дахь арга нь үйлдлийн системээр шууд дэмжигддэг кернелийн түвшиний сан суурьлуулах. Энэ нөхцөлд сангын код болон өгөгдлийн бүтцүүд нь кернелийн зайнд байрлана гэсэн үг. API –д байгаа санд зориулсан фунзц дуудалт нь ерөнхийдөө кернелрүү систем дуудлага хийж таардаг.

3 гол өнөө үед хэрэглэгдэж байгаа thread  сангууд : 1. POSIX Pthreads , 2. Wind32, болон 3. Java. Pthreads буюу POSIX стандартын thread өргөтгөл хэрэглэгч болон кернел түвшиний сангуудад түгээгдсэн байдаг. Win32 thread нь кернел түвшиний Windows үйлдлийн систем дээр хэрэглэгддэг сан. Java thread API нь thread үүсгэлт болон удирдлага, тохируулгыг шууд жава програмаас хий боломжийг олгодог. Гэвч ихэнхидээ JVM нь хостын үйлдлийн систем дээр ажилладаг болохоор Java thread API нь ерөнхийдөө хостын системд байгаа байгаа thread сангуудыг ашиглан суурьлагддаг. Энэ нь Windows системд , java thread –үүд нь Win32 ашиглаж суурьлагдана гэсэн үг unix болон linux нь голцуу Pthreads- ыг ашигладаг. 

Энэ хэсгийн үлдсэн хэсэгт энэ гурван thread сангууд дээрхи ерөнхий thread үүсгэлтийн талаар бичигдэх болно. Бид дүрстэй жишээгээр бидний мэдэх нэмэх функцаар сөрөг биш тоог thread үүдэд яаж хувааж хийдгийг харцгаая 

Жишээ нь. Хэрэв N=5 байсан бол энэ функц нь 0 –оос 5 хүртэлх тооны нийлбэрийг илэрхийлнэ гэсэн үг ба энэ 15 гэсэн үг. Эдгээр 3 програм нь аль аль нь коммандын мөрийн дээд талд хэрэгжинэ гэсэн үг цаашлаад хэрэв хэрэглэгч 8 гэж оруувбал 0-оос 8 хүртэлх тооны нийлбэр нь гаралтанд гарна гэсэн үг. 

## Pthreads
Pthreads нь POSIX стандартыг илэрхийлж байгаа ба (IEE 1003.1c) API-г thread үүсгэх болон синхрончилж байгаа гэдгийг тодорхойлж байгаа. Энэ нь thread –ын шинж чанарыг тодорхойлж байгаа ба суурьлуулалт бол биш.  Үйлдлийн системийн хийх ч нь өөрөө шинж чанарыг өөрийн хүссэнээрээ суурьлуулж болно.  Олон тооны системүүд Pthreads –ын шинж чанарыг хэрэглэдэг. Жишээ нь Solaris, Linux, Mac OS, мөн Tru64UNIX. Shareware суурьлуулалт нь windows үйлдлийн системүүдэд зориулагдан public domain үүд дээр мөн байдаг. 

4.6 зураг дээр байгаа С прорам нь ерөнхий Pthreads API-г ашиглан эерэг бүхэл тоон нийлбэрийг тусдаа thread дээр олдог multithread програмыг хэрхэн хийх талаар харуулсан байна. Pthread прогамд тусдаа thread үүд нь тодорхой функцээр эхэлдэг. Зураг 4,6д энэ бол Runner() функц. Энэ прорам нь эхлэх үед удирдлагын нэг thread нь main () д эхлэнэ. Хэсэг суурьлуулалтын дараа Main0 нь runner функц дээр байгаа удирдлагыг эхлүүлэх 2дахь thread ыг үүсгэнэ. Thread үүд нь  глобал өгөгдөл нэмэгдэлтийг ашиглана. 

include  

include 

int sum; /* this data is shared by the thread(s) */

void *runner(void *param); /* the thread */

int main(int argc, char *argv[])

{

pthread_t tid; /* the thread identifier */

pthread.attr_t attr; /* set of thread attributes */

if (argc != 2) {

fprintf(stderr,"usage: a.out \n");

return -1;

}

if (atoi(argv[1]) = 0\n",atoi(argv[1]));

return -1;

/* get the default attributes */

pthread.attr.init (&attr) ;

/* create the thread */

pthread^create(&tid,&attr,runner,argv[1]);

/* wait for the thread to exit */

pthread_join (tid, NULL) ;

printf("sum = %d\n",sum);

/* The thread will begin control in this function */

void *runner(void *param)

{

int i, upper = atoi(param);

sum = 0;

for (i = 1; i 

include 

DWORD Sum; /* data is shared by the thread(s) */

/* the thread runs in this separate function */

DWORD WINAPI Summation(LPVOID Param)

{

DWORD Upper = *(DWORD*)Param;

for (DWORD i = 0; i = 0 is required\n");

return -1;

// create the thread

ThreadHandle = CreateThread(

NULL, // default security attributes

0, // default stack size

Summation, // thread function

&Param, // parameter to thread function

0, // default creation flags

SThreadld); // returns the thread identifier

if (ThreadHandle != NULL) {

// now wait for the thread to finish

WaitForSingleObject(ThreadHandle,INFINITE);

// close the thread handle

CloseHandle(ThreadHandle);

printfC'sum = %d\n",Sum);

}

Ангилал:Зэрэгцээ тооцоолол
Ангилал:Үйлдлийн системийн онол