歡迎您光臨本站 註冊首頁

linux多線程機制線程同步

←手機掃碼閱讀     火星人 @ 2014-03-12 , reply:0
  

1.引言

  目前,許多流行的多任務操作系統都提供線程機制,線程就是程序中的 單個順序控制流。利用多線程進行程序設計,就是將一個程序(進程)的任務劃分為執行的多個部分(線程) ,每一個線程為一個順序的單控制流,而所有線程都是併發執行的,這樣,多線程程序就可以實現并行計算,高效利用多處理器。線程可分為用戶級線程和內核級線 程兩種基本類型。用戶級線程不需要內核支持,可以在用戶程序中實現,線程調度、同步與互斥都需要用戶程序自己完成。內核級線程需要內核參與,由內核完成線 程調度並提供相應的系統調用,用戶程序可以通過這些介面函數對線程進行一定的控制和管理。Linux操作系統提供了LinuxThreads庫,它是符合POSIX1003.1c標準的內核級多線程函數庫。在linuxthreads庫中提供了一些多線程編程的關鍵函數,在多線程編程時應包括pthread.h文件。

  2.LinuxThread中的關鍵庫函數

  2.1線程的創建和終止

  int pthread_create(pthread_t * pthread,const pthread_attr_t *attr,void *(*start_routine(*void)),void *arg);調用此函數可以創建一個新的線程,新線程創建后執行start_routine 指定的程序。其中參數attr是用戶希望創建線程的屬性,當為NULL時表示以默認的屬性創建線程。arg是向start_routine 傳遞的參數。當成功創建一個新的線程時,系統會自動為新線程分配一個線程ID號,並通過pthread 返回給調用者。

  void pthread_exit(void *value_ptr);調用該函數可以退出線程,參數value_ptr是一個指向返回狀態值的指針。

  2.2線程式控制制函數

  pthread_self(void);為了區分線程,在線程創建時系統為其分配一個唯一的ID號,由pthread_create()返回給調用者,也可以通過pthread_self()獲取自己的線程ID。

  Int pthread_join (pthread- t thread , void * *status);這個函數的作用是等待一個線程的結束。調用pthread_join()的線程將被掛起直到線程ID為參數thread 指定的線程終止。

  int pthread_detach(pthread_t pthread);參數pthread代表的線程一旦終止,立即釋放調該線程佔有的所有資源。

  2.3線程間的互斥

  互斥量和臨界區類似,只有擁有互斥量的線程才具有訪問資源的許可權, 由於互斥對象只有一個,這就決定了任何情況下共享資源(代碼或變數)都不會被多個線程同時訪問。使用互斥不僅能夠在同一應用程序的不同線程中實現資源的安 全共享,而且可以在不同應用程序的線程之間實現對資源的安全共享。Linux中通過pthread_mutex_t來定義互斥體機制完成互斥操作。具體的操作函數如下

  pthread_mutex_init(pthread_mutex_t *mutex,const pthread_mutexattr_t *attr);初使化一個互斥體變數mutex,參數attr表示按照attr屬性創建互斥體變數mutex,如果參數attr為NULL,則以默認的方式創建。

  pthread_mutex_lock(pthread_mutex_t *mutex);給一個互斥體變數上鎖,如果mutex指定的互斥體已經被鎖住,則調用線程將被阻塞直到擁有mutex的線程對mutex解鎖為止。

  Pthread_mutex_unlock(pthread_mutex_t *mutex);對參數mutex指定的互斥體變數解鎖。

  2.4線程間的同步

  同步就是線程等待某一個事件的發生,當等待的事件發生時,被等待的線程和事件一起繼續執行。如果等待的事件未到達則掛起。在linux操作系統中是通過條件變數來實現同步的。

  Pthread_cond_init(pthread_cond_t *cond,const pthread_cond_t *attr);這個函數按參數attr指定的屬性初使化一個條件變數cond。

  Pthread_cond_wait(pthread_cond_t *cond,pthread_mutex_t *mutex);等待一個事件(條件變數)的發生,發出調用的線程自動阻塞,直到相應的條件變數被置1。等待狀態的線程不佔用CPU時間。

  pthread_cond_signal(pthread_cond_t *cond);解除一個等待參數cond指定的條件變數的線程的阻塞狀態。

3.多線程編程的應用實例

  在這裡利用多線程技術實現生產者和消費者問題,生產者線程向一緩衝區中寫數據, 消費者線程從緩衝區中讀取數據,由於生產者線程和消費者線程共享同一緩衝區,為了正確讀寫數據,在使用緩衝隊列時必須保持互斥。生產者線程和消費者線程必 須滿足:生產者寫入緩衝區的數目不能超過緩衝區容量,消費者讀取的數目不能超過生產者寫入的數目。在程序中使用了一個小技巧來判斷緩衝區是空還是滿。在初 始化時讀指針和寫指針為0;如果讀指針等於寫指針,則緩衝區是空的;如果(寫指針+ 1) % N 等於讀指針,則緩衝區是滿的,%表示取餘數,這時實際上有一個單元空出未用。下面是完整的程序段和註釋。

  #include<stdio.h>

  #include<pthread.h>

  #define BUFFER_SIZE 8

  struct prodcons {

  int buffer[BUFFER_SIZE];

  pthread_mutex_t lock;      //互斥LOCK

  int readpos , writepos;

  pthread_cond_t notempty;   //緩衝區非空條件判斷

  pthread_cond_t notfull;    //緩衝區未滿條件判斷

  };

  void init(struct prodcons * b){

  pthread_mutex_init(&b->lock,NULL);

  pthread_cond_init(&b->notempty,NULL);

  pthread_cond_init(&b->notfull,NULL);

  b->readpos=0;

  b->writepos=0;

  }

  void put(struct prodcons* b,int data){

  pthread-_mutex_lock(&b->lock);

  if((b->writepos + 1) % BUFFER_SIZE == b->readpos)

  {

  pthread_cond_wait(&b->notfull, &b->lock) ;

  }

  b->buffer[b->writepos]=data;

  b->writepos++;

  if(b->writepos >= BUFFER_SIZE)

  b->writepos=0;

  pthread_cond_signal(&b->notempty);

  pthread_mutex_unlock(&b->lock);

  }

  int get(struct prodcons *b){

  int data;

pthread_mutex_lock(&b->lock);

  if(b->writepos == b->readpos)

  {

  pthread_cond _wait(&b->notempty, &b->lock);

  }

  data = b->buffer[b->readpos];

  b->readpos++;

  if(b->readpos >= BUFFER_SIZE)

  b->readpos=0;

  pthread_cond_signal(&b->notfull);

  pthread_mutex_unlock(&b->lock);

  return data;

  }

#define OVER (-1)

  struct prodcons buffer;

  void *producer(void *data)

  {

  int n;

  for(n = 0; n < 10000; n++)

  {

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

  put(&buffer, n);

  }

  put(&buffer, OVER);

  return NULL;

  }

  void *consumer(void * data)

  {

  int d;

  while(1)

  {

  d = get(&buffer);

  if(d == OVER)

  break;

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

  }

  return NULL;

  }

  int main(void)

  {

pthread_t th_a, th_b;

  void *retval;

  init(&buffer);

  pthread_create(&th_a, NULL, producer, 0);

  & nbsp;   pthread_create(&th_b, NULL, consumer, 0);

  pthread_join(th_a, &retval);

  pthread_join(th_b, &retval);

  return 0;

  }

  上 面的例子中,生產者負責將1到1000的整數寫入緩衝區,而消費者負責從同一個緩衝區中讀取寫入的整數並列印出來。因為生產者和消費者是兩個同時運行的線 程,並且要使用同一個緩衝區進行數據交換,因此必須利用一種機制進行同步。通過上面的例子我們可以看到,多線程的最大好處是,除堆棧之外,幾乎所有的數據 均是共享的,因此線程間的通訊效率很高;缺點:因為共享所有數據,從而非常容易導致線程之間互相破壞數據,這一點在編程時必須注意。

  4.結束語

  Linux中基於POSIX標準的很好的支持了多線程技術,它減少了程序併發執行時的系統開銷,提高了計算機的工作效率。在具體編程過程中要了解線程的間的關係,還要考慮共享數據的保護,在互斥和同步機制下保證代碼的高效運行,程序編譯時用gcc -D –REENTRANT -libpthread.xx.so filename.c編譯。



[火星人 ] linux多線程機制線程同步已經有415次圍觀

http://coctec.com/docs/program/show-post-71617.html