線程的同步與互斥

1. 互斥量

????在Linux 下線程使用的都是局部變量, 而我們知道, 每一個線程都獨立擁有自己的一個棧, 而這些局部便令就在棧中,而線程的創建就是為了實現通信, 此時線程之間無法共享這些變量
????為了使得線程之間能夠共享數據, 一次我們可以創建一個全局變量, 此時線程都在進程內部共享一個地址空間, 因此個線程之間就可以看到這個全局變量了
????但是問題又來了, 創建了全局變量, 線程之間其實看到了一份公共資源, 而此時一個線程之間由于共同訪問這個局部變量很有可能造成線程之間的不安全, 為了使得線程之間能夠正確訪問, 我們就引入了互斥量.我們規定,當代碼進入臨界區執行的時候, 不允許其他線程進入該臨界區. 當有多個線程要求執行臨界區的代碼時,此時如果臨界區沒有如何線程的時候, 操作系統只允許一個線程進入該臨界區, 而其他的線程則必須在臨界區外等待, 直到進入臨界區的線程走出臨界區, 并且釋放互斥量.如果線程不在臨界區內, 該線程不能組織其他線程進入臨界區

2.互斥量相關接口
1.初始化互斥量
pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t* restict attr);參數:mutex:要初始化的互斥量attr: NULL
2.銷毀互斥量
int pthread_mutex_destroy(pthread_mutex_t* mutex);
3.互斥量的加鎖
int pthread_mutex_lock(pthrea_mutex_t* mutex);
4.互斥量的解鎖
int pthread_mutex_unlock(pthread_mutex_t* mutex);

????注意, 互斥量處于互斥狀態時, 加鎖函數會將該互斥量鎖定, 同時返回成功, 當發起加鎖函數被調用的時候, 其他線程已經鎖定互斥量, 或者當好多線程同時申請互斥量的時候, 此時線程之間就在相互競爭這個互斥量,此時, 該函數調用將會陷入阻塞狀態,一直等待該互斥量, 直到擁有該互斥量的線程主動釋放該互斥鎖

#include<stdio.h>
#include<pthread.h>
#include<string.h>
#include<unistd.h>
#include<stdlib.h>int ticket = 100;
pthread_mutex_t mutex;
void* route(void* arg)
{char* id = (char*)arg;while(1){//pthread_mutex_lock(&mutex);if(ticket > 0){usleep(10000);printf("%s sells ticket:%d\n", id, ticket);ticket--;//pthread_mutex_unlock(&mutex);}else{//pthread_mutex_unlock(&mutex);break;}}
}
int main()
{pthread_t t1, t2, t3, t4;pthread_mutex_init(&mutex, NULL);pthread_create(&t1, NULL, route, "thread 1");pthread_create(&t2, NULL, route, "thread 2");pthread_create(&t3, NULL, route, "thread 3");pthread_create(&t4, NULL, route, "thread 4");pthread_join(t1, NULL);pthread_join(t2, NULL);pthread_join(t3, NULL);pthread_join(t4, NULL);return 0;
}

???????????????????????????????????這里寫圖片描述
????由上圖可以看出, 由于我們未加互斥鎖, 線程對數據的不正確操作造成了數據的錯誤,當我我們在線程進入臨界區的時候臨界資源加上互斥鎖, 而在線程離開臨界區的時候對互斥量進行釋放, 此時就不會出現數據錯誤的現象了
???????????????????????????????????這里寫圖片描述

3. 條件變量

????當一個線程互斥訪問某個變量時, 它可能發現在其他線程改變狀態的之前它什么也不能做, 例如一個線程訪問隊列時, 它發現這個隊列為空, 此時,它只能等待, 直到其他線程將結點放到該隊列.這時, 為了使得各個線程之間能夠同步的訪問這個變量,此時就需要有一個變量, 該變量必須要符合某個條件時, 線程才能訪問這個變量.

4. 相關接口
1. 初始化
int pthread_cond_init(pthread_cond_t* restrict cond, const pthread_condattr_t* restrict attr);cond: 表示要初始化的條件變量attr: NULL
2. 銷毀
int pthread_cond_destroy(pthread_cond_t* cond)
3. 等待條件滿足
int pthread_cond_wait(pthread_cond_t* restrict cond, pthread_mutex_t* restrict mutex);cond: 如果條件不滿足, 就在條件變量上等待mutex: 互斥量, 表名線程退出時必須釋放哪一個鎖
4. 喚醒
int pthread_cond_broadcast(pthread_cond_t* cond);用來喚醒一群線程
int pthread_cond_signal(pthread_cond_t* cond);用來喚醒某個線程

????也許你會問, 既然線程等待, 那就直接等待就好了, 有一個條件變量就可以了, 但是為什么好要有一個互斥量呢?通過上面所述, 我們知道, 條件變量是為了使得線程之間得到同步所采用的一種手段. 當只有一個線程的時候, 條件不滿足, 此時線程等待, 一直等待下去, 此時由于只有一個線程, 該線程所等待的條件將始終不會得到滿足, 一次線程將會一直等待下去. 所以, 為了能夠及時通知等待的線程, 必須有另外的線程對等待的這個條件(共享變量)做出預定的操作, 使得等待的線程所等待的條件得到滿足, 此時, 這個條件變量是一個共享變量, 為了使得每一個線程訪問該數據的正確性, 此時就必須引入互斥量來保證臨界資源的正確性.

#include<stdio.h>
#include<unistd.h>
#include<pthread.h>
#include<stdlib.h>
#include<string.h>pthread_cond_t cond;
pthread_mutex_t mutex;void* thread1(void* arg)
{while(1){printf("%s\n", (char*)arg);pthread_cond_wait(&cond, &mutex);printf("活動\n");}
}void* thread2(void* arg)
{while(1){sleep(2);printf("%s\n", (char*)arg);pthread_cond_signal(&cond);}
}
int main()
{pthread_t t1;pthread_t t2;pthread_cond_init(&cond, NULL);pthread_mutex_init(&mutex, NULL);pthread_create(&t1, NULL, thread1, "thread1");pthread_create(&t2, NULL, thread2, "thread2");pthread_join(t1, NULL);pthread_join(t2, NULL);pthread_cond_destroy(&cond);pthread_cond_destroy(&cond);return 0;
}

????上面代碼是用來創建線程1, 線程2, 同時線程在條件變量上進行等待, 直到有線程將其喚醒, 線程2睡眠一秒, 然后將等待 cond 的線程1喚醒, 此時線程2被喚醒, 它開始執行, 執行完之后,它有開始等待條件變量 cond直到條件變量 cond 滿足時再醒來.
???????????????????????????????????這里寫圖片描述
????通過上圖可以看出來, 線程2要活動, 它必須等待條件變量 cond 滿足時才能活動, 即線程2 必須在條件變量上等待, 直到線程 2 將其喚醒

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/384026.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/384026.shtml
英文地址,請注明出處:http://en.pswp.cn/news/384026.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

二級指針與指針數組的關系

http://blog.csdn.net/shuaishuai80/article/details/6129742 #include <stdio.h> void test(char *argv[]); int main(void) { char *argv[3]{{"abcdefg"},{"1234567"},{"q1w2e3r"}}; test(argv); /*調用指針數組…

UVa1584

【題目描述】 傳送門 【題目分析】 也是一道簡單的模擬題&#xff0c;1A嘿嘿嘿。 再看書發現和書上的做法差不多。 【AC代碼】 #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<queue> #include<cstd…

cf#582div3 D——暴力

【題目描述】 The only difference between easy and hard versions is the number of elements in the array.You are given an array a consisting of n integers. In one move you can choose any ai and divide it by 2 rounding down (in other words, in one move you c…

C語言 可變參數

http://www.cnblogs.com/zhanggaofeng/p/6434554.html //可變參數 #include <stdio.h> #include <stdlib.h> #include <string.h> //引用頭文件 #include <stdarg.h>/* va_list用于聲明一個變量&#xff0c;我們知道函數的可變參數列表其實就是一個字符…

UVa1585

【題目描述】 傳送門 【題目分析】 氵 【AC代碼】 #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<queue> #include<cstdlib> #include<set> #include<map> #include<vector>u…

c語言經典算法——查找一個整數數組中第二大數

https://www.cnblogs.com/dootoo/p/4473958.html 題目&#xff1a; 實現一個函數&#xff0c;查找一個整數數組中第二大數。 算法思想&#xff1a; 設置兩個變量max1和max2&#xff0c;用來保存最大數和第二大數&#xff0c;然后將數組剩余的數依次與這兩個數比較&#xff0c;如…

進程間關系和守護進程

一. 進程組/作業/會話 1.進程組 每一個進程除了有一個進程ID之外, 還屬于一個進程組. 進程是一個或多個進程的集合. 通常, 它們與同一個作業向關聯, 可以接收來自同一個終端下的各種命令,信號. 每一個進程組都有唯一的進程組 ID. 每一個進程組都可以有一個組長進程. 組長進程的…

UVa1586

【題目描述】 傳送門 【題目分析】 氵 【AC代碼】 #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<queue> #include<cstdlib> #include<set> #include<map> #include<vector> …

猴子偷桃問題

http://blog.csdn.net/snow_5288/article/details/52561882 問題描述&#xff1a; /*有一群猴子&#xff0c;去摘了一堆桃子*/ /*商量之后決定每天吃剩余桃子的一半*/ /*當每天大家吃完桃子之后&#xff0c;有個貪心的小猴都會偷偷再吃一個桃子*/ /*按照這樣的方式猴子們每天都…

UVa1225

【題目描述】 傳送門 【題目分析】 做題做多了慢慢都忘記暴力了&#xff0c;想要快速算出來&#xff0c;找到規律&#xff0c;但是找來找去好復雜的都沒有找到&#xff0c;然后寫了一個不能再暴力的寫法&#xff0c;就過了。。。 我還是覺得如果數據范圍變成1e9那種級別的還…

linux 線程學習之條件變量

http://blog.csdn.net/hemmanhui/article/details/4417433 互斥鎖&#xff1a;用來上鎖。 條件變量&#xff1a;用來等待&#xff0c;當條件變量用來自動阻塞一個線程&#xff0c;直到某特殊情況發生為止。通常條件變量和互斥鎖同時使用。 函數介紹&#xff1a; 1&#xff0e;…

UVa455

【題目描述】 傳送門 【題目分析】 就是一個簡單的暴力&#xff0c;只是需要注意輸出格式比較毒瘤。 【AC代碼】 #include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> #include<iostream> #include<cmath> #i…

網絡相關基礎概念

一. 相關基礎概念 1.計算機網絡的特點 (1)連通性:計算機網絡使得上網的用戶都能夠彼此相連, 好像用戶的計算機可以直接相連 ????(2)資源共享:資源共享可以是信息共享, 軟件共享, 硬件共享等等. 由于網絡的存在, 使得用戶感覺資源就在自己身邊 2. 網絡 網絡是由若干結點和…

linux線程同步(2)-條件變量

https://www.cnblogs.com/yuuyuu/p/5140875.html linux線程同步(2)-條件變量 一.概述 上一篇&#xff0c;介紹了互斥量。條件變量與互斥量不同&#xff0c;互斥量是防止多線程同時訪問共享的互斥變量來保護臨界區。條件變量…

UVa227

【題目描述】 傳送門 【題目分析】 題目的意思很簡單&#xff0c;只是輸入輸出很毒瘤&#xff0c;我一開始用的fgets然后用scanf(" ")吃掉所有的空格和換行&#xff0c;可是這樣有可能將迷宮的空格吃掉&#xff08;例如這個空格恰好在第一行第一列&#xff09;。 …

點對點數據鏈路層

數據鏈路層的主要功能將數據轉換為相應的比特流使用的信道主要有點對點的信道方式(一對一的方式), 以及廣播的信道方式 一. 點對點信道的數據鏈路層 1. 數據鏈路和數據幀 鏈路就是從一個結點連接到相鄰結點的一段物理線路(有線或者無線), 期間不準有任何的交換結點, 因此兩臺…

UVa232

[題目描述] 傳送門 [題目分析] 簡單的模擬,注意細節 [AC代碼] #include<cstdio> #include<cstring> #include<algorithm> #include<climits> #include<cctype> #include<queue> #include<set>using namespace std;typedef long…

linux線程同步(1)-互斥量

http://www.cnblogs.com/yuuyuu/p/5140251.html 一.概述 互斥量是線程同步的一種機制&#xff0c;用來保護多線程的共享資源。同一時刻&#xff0c;只允許一個線程對臨界區進行訪問。 互斥量的工作流程&#xff1a;創建一個…

UVa1368

[題目描述] 傳送門 [題目分析] 乍一看好像有點復雜,稍微思考一下只需要找到每個位置中最多的堿基.如果相等的話優先輸出字典序小的. [AC代碼] #include<cstdio> #include<cstring> #include<algorithm> #include<climits> #include<cctype>…

linux線程同步(3)-讀寫鎖

http://www.cnblogs.com/yuuyuu/p/5143881.html 一.概述 讀寫鎖與互斥量的功能類似&#xff0c;對臨界區的共享資源進行保護&#xff01;互斥量一次只讓一個線程進入臨界區&#xff0c;讀寫鎖比它有更高的并行性。讀寫鎖有…