前言:有個問題感覺一直會被問道:進程和線程的區別?也許之前我會回答: 進程:資源分配最小單位 線程:輕量級的進程 是系統調度的最小單位 由進程創建 多個線程共用進程的資源 但是現在我覺得一個比喻回答的更好:程式就像靜止的火車,進程是運行的火車,線程是運行火車的每節車廂。 個人感覺理解遠比背些概念性東 ...
前言:有個問題感覺一直會被問道:進程和線程的區別?也許之前我會回答:
- 進程:資源分配最小單位
- 線程:輕量級的進程 是系統調度的最小單位 由進程創建 多個線程共用進程的資源
但是現在我覺得一個比喻回答的更好:程式就像靜止的火車,進程是運行的火車,線程是運行火車的每節車廂。
個人感覺理解遠比背些概念性東西更好。
一、線程
通常在一個進程中可以包含若幹個線程,當然一個進程中至少有一個線程,不然沒有存在的意義。線程可以利用進程所擁有的資源,在引入線程的操作系統中,通常都是把進程作為分配資源的基本單位,而把線程作為獨立運行和獨立調度的基本單位,由於線程比進程更小,基本上不擁有系統資源,故對它的調度所付出的開銷就會小得多,能更高效的提高系統多個程式間併發執行的程度。
1、線程相關函數
- pthread_create函數
#include <pthread.h>
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine) (void *), void *arg);
註:Compile and link with -pthread.//編譯時 要加-lpthread
功能:創建線程
參數1:線程的ID
參數2:NULL
參數3:線程處理函數
參數4: 傳遞給線程處理函數的參數
成功放回0 失敗返回-1
- pthread_join函數
#include <pthread.h>
int pthread_join(pthread_t thread, void **retval);
功能:以阻塞的方式等待指定線程 主線程如果執行到此函數 將阻塞等待子線程結束
程式1-1演示兩個函數用法:
#include"my.h" void *func(void *p) { *(int*)p = 10; printf("%d\n",*(int *)p); } int main() { int x=100; pthread_t id; int ret = pthread_create(&id,NULL,func,&x); if(ret<0) { perror("pthread_create"); exit(-1); } pthread_join(id,NULL); return 0; }
註:頭文件“my.h”為自定義文件,詳情請參考這篇博客:http://www.cnblogs.com/liudw-0215/p/8946879.html
運行演示如下圖:
二、信號量
信號量(Semaphore),有時被稱為信號燈,是在多線程環境下使用的一種設施, 它負責協調各個線程, 以保證它們能夠正確、合理的使用公共資源。
1、信號量相關函數
- sem_init函數
sem_t s;
#include <semaphore.h>
int sem_init(sem_t *sem, int pshared, unsigned int value);
格式:sem_init(&s,0,n)
功能:初始化一個信號量的值為value
參數2:是否在進程間使用 一般總是0 表示不在進程間使用
參數3:計數器的初始值
- sem_wait函數
int sem_wait(sem_t *sem);
把計數器減一 它會等待 直到信號量有個非零值才會執行減法操作
如果對值為0的信號量用sem_wait 這個函數會等待 直到其他線程增加該信號量的值 使其不再是0為止
如果對值為2的信號量調用sem_wait 線程會繼續執行 但信號量的值會減一。
如果兩個線程同時在sem_wait調用上等待同一個信號量變為非0值 那麼當信號量 被第三個線程+1 只有一個等待線程開始對信號量-1
然後繼續執行 另一個線程還繼續等待。
- sem_post函數
#include <semaphore.h>
int sem_post(sem_t *sem);
功能:把 計數器+1
程式2-1介紹信號量使用
#include"my.h" sem_t s; void *fun(void *p) { int i; int *pa = (int *)p; for(i=0;i<4;i++) { sem_wait(&s);//將計數器的值-1 pa[i] +=i; } for(i=0;i<4;i++) { printf("%-02d",pa[i]); } printf("\n"); return NULL; } void *fun1(void *p) { sem_wait(&s);//將計數器的值-1 puts("fun1 run!"); return NULL; } int main() { int i=0,ret=0; int a[5]={0}; sem_init(&s,0,0);//設置信號量的值為0 pthread_t tid[2]; ret = pthread_create(&tid[0],NULL,fun,a); if(ret<0) { perror("pthread_create"); exit(-1); } ret = pthread_create(&tid[1],NULL,fun1,a); if(ret<0) { perror("pthread_create"); exit(-1); } for(i=0;i<5;i++) { sem_post(&s);//將計數器的值+1 } pthread_join(tid[0],NULL); pthread_join(tid[1],NULL); return 0; }
運行演示如下圖:
三、互斥鎖
互斥鎖: 只要被鎖住,其他任何線程都不可以訪問被保護的資源
1、互斥鎖相關函數
pthread_mutex_t m;
pthread_mutex_init(&m,NULL) //初始化互斥量
pthread_mutex_lock(&m);//對一個互斥量加鎖 如果互斥量已經加鎖 函數會一直等待 等到有線程把這個互斥量解鎖後 再去加鎖
pthread_mutex_unlock(&m);//對一個互斥量解鎖 哪個線程加鎖只能由這個線程解鎖 別的線程不能 解鎖
程式3-1演示互斥鎖應用:
#include"my.h" pthread_mutex_t m; void* thread_fun(void *p) { int i; pthread_mutex_lock(&m);//加鎖 for(i=0;i<3;i++) { printf("PID:%d tid:%lu\n",getpid(),pthread_self()); sleep(1); } pthread_mutex_unlock(&m);//解鎖 pthread_exit(NULL); } int main() { pthread_mutex_init(&m,NULL);//初始化鎖 int i,ret; pthread_t tid[3]; for(i=0;i<3;i++) { ret = pthread_create(&tid[i],NULL,thread_fun,NULL); if(ret<0) { printf("pthread_create %d error\n",i); exit(-1); } } for(i=0;i<3;i++) { pthread_join(tid[i],NULL); } return 0; }
運行演示如下圖:
總結:主要介紹線程同步的信號量和互斥鎖,以後有時間將更加詳細介紹其中實現原理。