標籤:地址空間 資源 共用資料 thread linux中 next ext std bsp
在Linux中,多線程的本質仍是進程,它與進程的區別:
進程:獨立地址空間,擁有PCB
線程:也有PCB,但沒有獨立的地址空間(共用)
線程的特點:
1,線程是輕量級進程,有PCB,建立線程使用的底層函數和進程一樣,都是clone
2,從核心看進程和線程是一樣的,都有各自不同的PCB
3,進程可以蛻變成線程
4,在LINUX中,線程是最小的執行單位,進程是最小的分配資源單位
查看指定線程的LWP號命令:
ps -Lf pid
線程優點:
提高程式並發性
開銷小
資料通訊,共用資料方便
線程缺點:
庫函數 ,不穩定
調試,編寫困難,GDB
對訊號支援不好
線程屬性,可以在一開始就設定好分離態,具體在下面的代碼有說明!
線程同步,主要有互斥鎖mutex,讀寫鎖,條件變數,訊號量
線程建立函數原型:
int pthread_create( pthread_t *thread, // 線程ID const pthread_attr_t *attr, // 線程屬性 void *(*start_routine) (void *), // 線程主函數 void *arg// 主函數參數);
粘上基本建立執行緒模式:
#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sys/types.h>#include <unistd.h>#include <pthread.h>//函數回調void *mythread(void *args){printf("child thread id==[%ld]\n", pthread_self());}int main(){pthread_t thread;//建立一個線程int ret = pthread_create(&thread, NULL, mythread, NULL);if(ret!=0){printf("pthread_create error, [%s]\n", strerror(ret)); return -1;}printf("main thread id==[%ld]\n", pthread_self());sleep(1);}
線程屬性,在建立時分離代碼:
#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sys/types.h>#include <unistd.h>#include <pthread.h>void *mythread(void *args){printf("child thread id==[%ld]\n", pthread_self());}int main(){pthread_t thread;//線程屬性pthread_attr_t attr;//線程屬性初始化pthread_attr_init(&attr);//設定線程到分離屬性pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);//建立一個線程int ret = pthread_create(&thread, &attr, mythread, NULL);if(ret!=0){printf("pthread_create error, [%s]\n", strerror(ret)); return -1;}printf("main thread id==[%ld]\n", pthread_self());sleep(1);ret = pthread_join(thread, NULL);if(ret!=0){printf("pthread_join error, [%s]\n", strerror(ret));}//釋放線程屬性pthread_attr_destroy(&attr);return 0;}
互斥鎖實現代碼:
#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sys/types.h>#include <unistd.h>#include <pthread.h>#include <time.h>//定義一把鎖pthread_mutex_t mutex;void *mythread1(void *args){while(1){//加鎖pthread_mutex_lock(&mutex);pthread_mutex_lock(&mutex);printf("hello ");sleep(rand()%3);printf("world\n");//解鎖pthread_mutex_unlock(&mutex);sleep(rand()%3);}pthread_exit(NULL);}void *mythread2(void *args){while(1){//加鎖pthread_mutex_lock(&mutex);printf("HELLO ");sleep(rand()%3);printf("WORLD\n");//解鎖pthread_mutex_unlock(&mutex);sleep(rand()%3);}pthread_exit(NULL);}int main(){int ret;pthread_t thread1;pthread_t thread2;//隨機數種子srand(time(NULL));//互斥鎖初始化pthread_mutex_init(&mutex, NULL);ret = pthread_create(&thread1, NULL, mythread1, NULL);if(ret!=0){printf("pthread_create error, [%s]\n", strerror(ret));return -1;}ret = pthread_create(&thread2, NULL, mythread2, NULL);if(ret!=0){printf("pthread_create error, [%s]\n", strerror(ret));return -1;}//等待線程結束pthread_join(thread1, NULL);pthread_join(thread2, NULL);//釋放互斥鎖pthread_mutex_destroy(&mutex);return 0;}
讀寫鎖代碼:
#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sys/types.h>#include <unistd.h>#include <pthread.h>int number = 0;//定義一把讀寫鎖pthread_rwlock_t rwlock;void *fun_write(void *args){int i = *(int *)args;int n;while(1){//加寫鎖pthread_rwlock_wrlock(&rwlock);n = number;n++;//sleep(rand()%3);number = n;printf("W->[%d]:[%d]\n", i, number);//解寫鎖pthread_rwlock_unlock(&rwlock);sleep(rand()%3);}pthread_exit(NULL);}void *fun_read(void *args){int i = *(int *)args;while(1){//加讀鎖pthread_rwlock_rdlock(&rwlock);printf("R->[%d]:[%d]\n", i, number);//解鎖pthread_rwlock_unlock(&rwlock);sleep(rand()%3);}pthread_exit(NULL);}int main(){int i;int ret;int n = 8;int arr[8];pthread_t thread[8];//讀寫鎖初始化pthread_rwlock_init(&rwlock, NULL);//建立3個寫線程for(i=0; i<3; i++){arr[i] = i;ret = pthread_create(&thread[i], NULL, fun_write, (void *)&arr[i]);if(ret!=0){printf("pthread_create error, [%s]\n", strerror(ret));return -1;}}//建立5個讀線程for(i=3; i<n; i++){arr[i] = i;ret = pthread_create(&thread[i], NULL, fun_read, (void *)&arr[i]);if(ret!=0){printf("pthread_create error, [%s]\n", strerror(ret));return -1;}}for(i=0; i<n; i++){//回收子線程pthread_join(thread[i], NULL);}//釋放讀寫鎖資源pthread_rwlock_destroy(&rwlock);return 0;}
cond條件變數代碼:
#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sys/types.h>#include <unistd.h>#include <pthread.h>typedef struct node{int data;struct node *next;}NODE;//鏈表前端節點指標NODE *head = NULL;//互斥鎖pthread_mutex_t mutex;//條件變數pthread_cond_t cond;//生產者線程處理函數void *producer(void *args){NODE *pNode = NULL;while(1){pNode = (NODE *)malloc(sizeof(NODE));if(pNode==NULL){perror("malloc error\n");exit(1);}pNode->data = rand()%1000;//lock共用資源 pthread_mutex_lock(&mutex);pNode->next = head;head=pNode;printf("P:[%d]\n", head->data);//對共用資源解鎖pthread_mutex_unlock(&mutex);//使用條件變數解除對線程到阻塞pthread_cond_signal(&cond);sleep(rand()%3);}}//消費者線程處理函數void *consumer(void *args){NODE *pNode = NULL;while(1){//lock共用資源 pthread_mutex_lock(&mutex);if(head==NULL){//條件不滿足阻塞等待head不為空白pthread_cond_wait(&cond, &mutex);}printf("C:[%d]\n", head->data);pNode = head;head = head->next;//對共用資源解鎖pthread_mutex_unlock(&mutex);free(pNode);pNode = NULL;sleep(rand()%3);}}int main(int argc, char *argv[]){int ret;pthread_t thread1;pthread_t thread2;pthread_mutex_t mutex;pthread_cond_t cond;//初始化互斥鎖pthread_mutex_init(&mutex, NULL);//初始化條件變數pthread_cond_init(&cond, NULL);//建立生產者線程ret = pthread_create(&thread1, NULL, producer, NULL);if(ret!=0){printf("pthread_create error, [%s]\n", strerror(ret));return -1;}//建立消費者線程ret = pthread_create(&thread2, NULL, consumer, NULL);if(ret!=0){printf("pthread_create error, [%s]\n", strerror(ret));return -1;}//主線程回收子線程pthread_join(thread1, NULL);pthread_join(thread2, NULL);//釋放鎖資源pthread_mutex_destroy(&mutex);//釋放條件變數資源pthread_cond_destroy(&cond);return 0;}
訊號量,經典消費者生產者模型:
#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sys/types.h>#include <unistd.h>#include <pthread.h>#include <semaphore.h>typedef struct node{int data;struct node *next;}NODE;//鏈表前端節點指標NODE *head = NULL;sem_t sem_consumer;sem_t sem_producer;//生產者線程處理函數void *producer(void *args){NODE *pNode = NULL;while(1){pNode = (NODE *)malloc(sizeof(NODE));if(pNode==NULL){perror("malloc error\n");exit(1);}pNode->data = rand()%1000;//sem_producer--, 若為0則阻塞sem_wait(&sem_producer);pNode->next = head;head=pNode;printf("P:[%d]\n", head->data);//sem_consumer++sem_post(&sem_consumer);sleep(rand()%3);}}//消費者線程處理函數void *consumer(void *args){NODE *pNode = NULL;while(1){//sem_consumer--, 若為0則阻塞sem_wait(&sem_consumer);printf("C:[%d]\n", head->data);pNode = head;head = head->next;//sem_producer++sem_post(&sem_producer);free(pNode);pNode = NULL;sleep(rand()%3);}}int main(int argc, char *argv[]){int ret;pthread_t thread1;pthread_t thread2;//訊號量初始化sem_init(&sem_producer, 0, 5);sem_init(&sem_consumer, 0, 0);//建立生產者線程ret = pthread_create(&thread1, NULL, producer, NULL);if(ret!=0){printf("pthread_create error, [%s]\n", strerror(ret));return -1;}//建立消費者線程ret = pthread_create(&thread2, NULL, consumer, NULL);if(ret!=0){printf("pthread_create error, [%s]\n", strerror(ret));return -1;}//主線程回收子線程pthread_join(thread1, NULL);pthread_join(thread2, NULL);//釋放訊號量資源sem_destroy(&sem_producer);sem_destroy(&sem_consumer);return 0;}
Linux多線程實現及線程同步函數分析