Minggu, 14 Juni 2020

POSIX Threads

Thread merupakan sebuah alur kontrol proses yang dapat dijadwalkan pengeksekusiannya oleh sistem operasi. Selanjutnya, bayangkan sebuah program main mempunyai berbagai prosedur (fungsi) dan fungsi-fungsi tersebut dapat dijalankan secara serentak dan atau bebas dijalankan oleh sistem operasi. Dan itulah yang disebut sebagai multithread.
Yang perlu diketahui sebelum kita mempelajari thread yaitu pertama kita harus mengetahui tentang UNIX process. Sebuah proses diciptakan oleh sistem operasi dan membutuhkan cukup banyak “overhead”. Proses terdiri dari informasi tentang sumber daya program dan posisi eksekusi proses :
o   Process ID, process group ID, user ID, and group ID
o   Environment
o   Working directory.
o   Program instructions
o   Registers
o   Stack
o   Heap
o   File descriptors
o   Signal actions
o   Shared libraries
o   Inter-process communication tools (such as message queues, pipes, semaphores, or shared memory)
Sebuah thread digunakan dan berada pada proses dan dapat secara bebas dieksekusi oleh sistem informasi. Aliran kontrol secara bebas ini dapat dicapai karena thread terdiri dari :
o   Stack pointer
o   Registers
o   Scheduling properties (such as policy or priority)
o   Set of pending and blocked signals
o   Thread specific data.
Kesimpulannya thread dalam UNIX :
o   Ada didalam proses dan menggunakan sumber daya.
o   Memiliki aliran kontrol sendiri selama proses induknya ada dan didukung OS.
o   Hanya menduplikat sumber daya penting untuk dapat berjalan sendiri.
o   Dapat berbagi sumber daya dengan thread lain yang sama-sama berjalan secara independen.
o   Akan mati jika proses induknya mati.
Apakah yang kemudian dimaksud dengan pthread?
Sejarahnya setiap vendor hardwar membuat implementasikan thread mereka masing-masing sehingga membuat programmer kesulitan dalam mengembangkan aplikasi portable dari hardware tersebut.Oleh karena itu untuk mencapai keuntungan yang optimal dari thread diperlukan suatu standar interface dari pemrograman thread.
1.     Pada sistem unix, interface dispesifikasikan dalam IEEE POSIX 1003.1c standard (1995).
2.     Implementasi dari thread sesuai standar tadi kemudian disebut POSIX thread atau disingkat pthread.
3.     Sekarang berbagai vendor hardware menyediakan Pthread pada API hardware mereka.
Kenapa menggunakan pthread?
Pada dunia komputer dengan kebutuhan tinggi, motivasi menggunakan pthread adalah mewujudkan perfomance yang optimal. Kemudian perbandingan biaya yang lebih murah dari proses, sebuah thread lebih murah dalam sumber dayanya dalam hal ini “overhead”. Pengelolaan thread juga lebih murah dari pada pengelolaan proses.
The Pthreads API
Pthread’s API telah didefinisikan pada ANSI/IEEE POSIX 1003.1 – 1995 standard. Standar ini terus dikembangkan dan mengalami revisi termasuk spesisfikasi thread.
Subroutine yang termasuk diantaranya dibagi menjadi 4 kategori yaitu :
1.     Pengelolaan thread (thread management) : merupakan routine yang beroperasi langsung terhadap thread. (create, detach, join dll). Termasuk juga didalamnya routine untuk mengeset atribut thread.
2.     Mutexes : Merupakan routine yang berhubungan dengan sinkronisasi atau biasa disebut “mutex” (mutual exlusion). Fungsi mutex menyediakan perintah untuk membuat, menghancurkan, mengunci dan membuka kunci mutex. Kemudian ditambah juga dengan fungsi untuk mengeset atribut yang terkait dengan mutex.
3.     Condition Variable : merupakan fungsi variable berkondisi tertentu yang digunakan untuk kebutuhan komunikasi antara thread dan mutex.
4.     Synchronization : routine yang mengatur baca/tulis kunci dan “barrier”.





Setiap routine pthread semuanya diawali dengan pthread_ . Dan berikut tabel berisi comand untuk mngkompile pada setiap platform.
COMPILER / PLATFORM
COMPILER COMMAND
DESCRIPTION
INTEL
Linux
icc -pthread
C
icpc -pthread
C++
PGI
Linux
pgcc -lpthread
C
pgCC -lpthread
C++
GNU
Linux, Blue Gene
gcc -pthread
GNU C
g++ -pthread
GNU C++
IBM
Blue Gene
bgxlc_r  /  bgcc_r
C (ANSI  /  non-ANSI)
bgxlC_r, bgxlc++_r
C++
Thread Management
Membuat thread : pthread_create (thread,attr,start_routine,arg) 
Perintah diatas digunakan untuk membuat thread dan membuatnya dapat dieksekusi. Routine ini dapat dipanggil berkali-kali di dalam kode anda.
Argumen pada pthread_create :
thread : merupakan pengenal dari sebuah thread yang dibuat.
attr : merupakan atribut objek yang mungkin digunakan untuk mengeset atribut thread. Anda bisa mengesetnya atau NULL untuk nilai default.
start_routine : merupakan fungsi pada C yang digunakan sebagai perintah untuk thread.
arg : merupakan nilai tunggal yang akan di passingkan ke start_routine. passing yang ditentukan menggunakan passing by reference sebagai pinter pada tipe void. Gunakan NULL untuk nilai default.
Attribut thread :
Secara default sebuah thread mempunyai attribut. Beberapa atribut dapat dirubah oleh programmer menggunakan thread object atribut. pthread_attr_init(attr) dan pthread_attr_destroy(attr) digunakan untuk mengeset dan menghancurkan atribut pada thread.
Menghentikan thread : pthread_exit()
Suatu thread dapat berhenti melalui beberapa cara diantaranya :
– thread berhenti dengan normal saat pekerjaannya telah selesai.
– thread dibatalkan dengan routine pthread_cancel.
– semua proses diberhentikan dengan fungsi system exec atau exit ().
– berakhirnya perintah pada main().
– pemberhentian melalui pemanggilan pthread_exit(), baik pekerjaannya telah selesai atau belum.
Contoh penggunaan  pthread_create dan pthread_exit :
#include <pthread.h>
#include <stdio.h>
#include <stdlib.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);
       }
     }

   /* Last thing that main() should do */
   pthread_exit(NULL);
}
Joining and detaching threads
Joining (Bergabung) merupakan salah satu cara untuk mensinkronisasikan antar thread.
The pthread_join Function digunakan  untuk menunda thread yang sekarang sampai thread yang dispesifikan dihentikan atau terhenti. Return value thread lain akan disimpan pada alamat memory yang ditunjuk oleh thread_return jika nilainya tidak NULL. Sumber daya memory yang digunakan oleh sebuah thread tidak akan dialokasikan sampai pthread_join selesai menggunakan. Jadi routin pthread_join harus dipanggil sekali pada setiap thread yang terhubung. Thread harus dapat digabungkan(joinable) bukan pada posisi detach (detached state) dan tidak ada thread lain yang mencoba menggunakan pthread_join pada thread yang sama. Thread bisa pada kondisi detach state dengan menggunakan pendekatan argumen attr saat pthread_create atau dengan memanggil routine pthread_detachKemudian juga pthread_detach juga digunakan untuk memisahkan thread yang berada pada kondisi joinable / terhubung. Contoh penggunaan :
#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);
}

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 detached 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);
}
Akan menghasilkan output sebagai berikut :
Main: creating thread 0
Main: creating thread 1
Thread 0 starting...
Main: creating thread 2
Thread 1 starting...
Main: creating thread 3
Thread 2 starting...
Thread 3 starting...
Thread 1 done. Result = -3.153838e+06
Thread 0 done. Result = -3.153838e+06
Main: completed join with thread 0 having a status of 0
Main: completed join with thread 1 having a status of 1
Thread 3 done. Result = -3.153838e+06
Thread 2 done. Result = -3.153838e+06
Main: completed join with thread 2 having a status of 2
Main: completed join with thread 3 having a status of 3
Main: program completed. Exiting.
Pembatalan thread 
fungsi pthread_cancel membolehkan thread sekarang membatalkan thread lain.
int pthread_cancel (pthread_t thread);
int pthread_setcancelstate ( int state, int *oldstate);
int pthread_setcanceltype ( int type, int *oldtype);
void pthread_testcancel(void);
Sebuah thread mengeset state pembatalan menggunakan pthread_statecancelstate yang mana mempunyai dua argumen. Argumen state merupakan state yang baru, dan argumen oldstate adalah pointer ke variable yang menyimpan state thread yang lama (oldstate) jika oldstate tidak null. Jika state adalah PTHREAD_CANCEL_ENABLE, maka permintaan pembatalan akan dilakukan. Sedangkan jika state pada kondisi PTHREAD_CANCEL_DISABLE maka permintaan pembatalan akan diabaikan.
Fungsi pthread_setcanceltype merubah bagaimana sebuah respon thread menjadi permintaan pembatalan. Jika type adalah PTHREAD_CANCEL_ASYNCHRONOUS thread akan dibatalkan dengan segera. Sedangkan jika type adalah PTHREAD_CANCEL_DEFERRED maka akan menunda pembatalan sampai tercapai titik pembatalan (cancelation point). Titik pembatalan dapat dicapai dengan memanggil fungsi pthread_testcancel(void) yang mana akan membatalkan thread sekarang jika ada penangguhan permintaan pembatalan yang tertunda. Fungsi cancel diatas mengembalikan nilai 0 jika sukses dan error untuk nilai lainnya kecuali fungsi pthread_cancel tidak mengembalikan value.

Tidak ada komentar:

Posting Komentar