公共資源
也稱為共享資源,是指可以被多個并發進程或線程共同訪問(讀取或寫入)的系統資源。
臨界資源
是公共資源的一個子集。特指那些一次僅允許一個進程或線程訪問的公共資源。如果一個進程正在使用它,其他試圖訪問該資源的進程必須等待,直到當前訪問完成。
臨界區
指進程中訪問臨界資源的那段代碼。它不是資源本身,而是操作資源的代碼段。 目標:確保當一個進程在臨界區內執行時,其他任何進程都不能進入其自身的臨界區(訪問同一個臨界資源)。
互斥
是一種機制、原則或屬性,用于保證對臨界資源的互斥訪問。它要求在任何時刻,最多只能有一個執行流(進程或線程)進入與某一臨界資源相關的臨界區。
互斥量
作用:用于線程的互斥,以避免對臨界資源訪問時沖突問題。
用法:通常在進入臨界區之前加鎖,退出臨界區時解鎖。
類型:pthread_mutex_t定義變量:pthread_mutex_t mutex;
操作:初始化(兩種方法)1. pthread_mutex_init(&mutex, NULL);//此方法需要銷毀2. pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;//此方法不需要銷毀加鎖: pthread_mutex_lock(&mutex);已經被加鎖,線程阻塞。pthread_mutex_trylock(&mutex);已經被加鎖,線程不阻塞,通過返回值判斷所得狀態。解鎖:pthread_mutex_unlock(&mutex);銷毀: pthread_mutex_destroy(&mutex);
死鎖
什么是死鎖:
多進程或多線程,在競爭資源的時候,由于互相搶占而導致僵死的狀態叫做死鎖。
死鎖是由于一方拿到資源不釋放。而其他線程或進程無法獲取資源導致。
解決死鎖的方法:
使用非阻塞方式拿鎖,不等待。
- 拿到做做事,拿不到鎖做其他的事。
獲取多個互斥量時規定拿鎖的順序。
- 如有A、B兩個鎖,規定先拿A再拿B,拿不到A就不允許拿B。
互斥量允許強制剝奪。
- 如果有線程占用互斥量時間過長,允許其他線程強制剝奪互斥量。
示例代碼
#include?<unistd.h>
#include?<sys/stat.h>
#include?<fcntl.h>#include?<pthread.h>#define?MAX_THREADS (5)??// 最大的線程個數static?int?is_running =?1;
// 針對 is_running 這個資源的鎖
static?pthread_mutex_t?running_lock;// 臨界資源i
static?long?int?i =?0;
// 針對 i 這個資源的鎖,并初始化
static?pthread_mutex_t?count_lock = PTHREAD_MUTEX_INITIALIZER;
// 定義一個線程處理函數
void?*?mythread(void* data)?{long?int?arg = (long?int)data;char?charactor =?'a'?+ arg;while(1) {int?run;pthread_mutex_lock(&running_lock);run = is_running;pthread_mutex_unlock(&running_lock);if?(!run)break;// 對i 這個臨界資源加鎖pthread_mutex_lock(&count_lock);if?(i == arg) {printf("%c", charactor);fflush(stdout);i = (i +?1) % MAX_THREADS;}// 解鎖pthread_mutex_unlock(&count_lock);}return?data;
}int?main(int?argc,?char?* argv[])?{pthread_t?thread[MAX_THREADS];int?ret;printf("請輸入回車開始和結束線程\n");getchar();// 初始化運行狀態鎖pthread_mutex_init(&running_lock,?NULL);for?(long?int?i =?0; i < MAX_THREADS; i++) {void?*varg = (void*)i;ret = pthread_create(&thread[i],?NULL, mythread, varg);if?(ret) {printf("pthread_create error: %d\n", ret);return?1;}}// 等待回車getchar();pthread_mutex_lock(&running_lock);is_running =?0;pthread_mutex_unlock(&running_lock);// 殺死所有的線程// for (int i = 0; i < MAX_THREADS; i++) {// pthread_cancel(thread[i]);// }?// 等待回收資源for?(int?i =?0; i < MAX_THREADS; i++) {void?* pret;pthread_join(thread[i], &pret);printf("pret:%p\n", pret);}?// 銷毀運行狀態鎖pthread_mutex_destroy(&running_lock);printf("主進程結束\n");return?0;
}
條件變量:
條件變量是一種線程同步機制,他允許一個線程在某個條件不滿足時主動進入等待狀態并釋放鎖,直到另一個線程改變這個條件后再通知其他線程繼續運行。
核心思想:以等代查。
定義條件變量:pthread_cond_t mycond;
操作:初始化(兩種方法)1. pthread_cond_init(&mycond, NULL);//此方法需要銷毀2. pthread_cond_t mycond = PTHREAD_COND_INITIALIZER;//此方法不需要銷毀等待條件: pthread_cond_wait(&mycond, &mutex);喚醒等待的線程:pthread_cond_signal(&mycond); // 喚醒一個線程pthread_cond_broadcast(&mycond); // 廣播喚醒全部線程。銷毀: pthread_cond_destroy(&mycond);
示例代碼:
#include?<stdio.h>
#include?<string.h>
#include?<sys/types.h>
#include?<unistd.h>
#include?<sys/stat.h>
#include?<fcntl.h>#include?<pthread.h>#define?MAX_THREADS (5)??// 最大的線程個數static?int?is_running =?1;
// 針對 is_running 這個資源的鎖
static?pthread_mutex_t?running_lock;// 臨界資源i
static?long?int?i =?0;
// 針對 i 這個資源的鎖,并初始化
static?pthread_mutex_t?count_lock = PTHREAD_MUTEX_INITIALIZER;
// 定義 i 這個資源的條件變量,并初始化
static?pthread_cond_t?count_cond = PTHREAD_COND_INITIALIZER;// 定義一個線程處理函數
void?*?mythread(void* data)?{long?int?arg = (long?int)data;char?charactor =?'a'?+ arg;while(1) {int?run;// pthread_mutex_lock(&running_lock);run = is_running;// pthread_mutex_unlock(&running_lock);if?(!run)break;// 對i 這個臨界資源加鎖pthread_mutex_lock(&count_lock);while( i != arg && is_running !=?0) {pthread_cond_wait(&count_cond, &count_lock);}if?(i == arg) {printf("%c", charactor);fflush(stdout);i = (i +?1) % MAX_THREADS;// 喚醒條件變量關聯的其他線程。// pthread_cond_signal(&count_cond); //喚醒一個線程pthread_cond_broadcast(&count_cond);?//喚醒全部}/* else {// 現在不應當我來打印。解鎖睡覺等待條件變化pthread_cond_wait(&count_cond, &count_lock);// 如果返回,說明條件變化,立即加鎖做事情}*/// 解鎖pthread_mutex_unlock(&count_lock);}return?data;
}int?main(int?argc,?char?* argv[])?{pthread_t?thread[MAX_THREADS];int?ret;printf("請輸入回車開始和結束線程\n");getchar();// 初始化運行狀態鎖pthread_mutex_init(&running_lock,?NULL);for?(long?int?i =?0; i < MAX_THREADS; i++) {void?*varg = (void*)i;ret = pthread_create(&thread[i],?NULL, mythread, varg);if?(ret) {printf("pthread_create error: %d\n", ret);return?1;}}// 等待回車getchar();pthread_mutex_lock(&running_lock);is_running =?0;pthread_mutex_unlock(&running_lock);// 再次喚醒所有的進程退出。pthread_cond_broadcast(&count_cond);?//喚醒全部// 殺死所有的線程// for (int i = 0; i < MAX_THREADS; i++) {// pthread_cancel(thread[i]);// }?// 等待回收資源for?(int?i =?0; i < MAX_THREADS; i++) {void?* pret;pthread_join(thread[i], &pret);printf("pret:%p\n", pret);}?// 銷毀運行狀態鎖pthread_mutex_destroy(&running_lock);printf("主進程結束\n");return?0;
}
網絡IPC
IP 地址(Internet Protocal Address):
IP 地址是記錄一個網絡設備的邏輯地址。
IP地址的分類:
IPv4: 用 32bit 來標識網絡設備(四個字節)
- 192.168.1.100
IPv6:用 128bit 來標識網絡設備
- 不穩定,是未來的發展趨勢。
端口號(port):
用來記錄網路設備上特定進程的關聯號碼。是一個16位的無符號性整數。
值 1~65535
IP 地址和子網掩碼
A類:255.0.0.0
B類:255.255.0.0
C類:255.255.255.0
查看IP地址的命令:
#?Windows?
ipconfig
#?早期 Linux/UNIX
ifconfig
#?Ubuntu Linux?
ip a
ip addr
ip address
內容如下:
inet 192.168.33.151/24 brd 192.168.33.255 scope global dynamic noprefixroute ens33# IP 地址: 192.168.33.151
# 廣播地址:192.168.33.255
# 子網掩碼: /24 表示 (255.255.255.0)IP 地址 & 子網掩碼 = 192.168.33.151 & 255.255.255.0 = 192.168.33.0 本網路的地址