1.線程互斥
1-1 進程線程間的互斥相關背景概念
臨界資源:多線程執行流共享的資源就叫做臨界資源
臨界區:每個線程內部訪問臨界資源的代碼就叫做臨界區
互斥:任何時刻,互斥保證只有一個執行進入臨界區,對臨界資源起到保護作用
原子性:不會被任何調度打斷的操作,只有兩種狀態一個是完成一個是未完成
1-2互斥量mutex
大部分情況線程使用的數據都是局部變量,變量的地址存放在線程棧空間里面,這種情況,變量歸屬單個線程,其他線程無法獲得該變量。有的時候多個線程需要對同一個變量進行操作找個變量稱為共享變量,多個線程并發的操作共享變量會帶來一些問題
// 操作共享變量會有問題的售票系統代碼
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
int ticket = 100;void *route(void *arg)
{
char *id = (char*)arg;
while ( 1 ) {
if ( ticket > 0 ) {
usleep(1000);
printf("%s sells ticket:%d\n", id, ticket);
ticket--;}
else {break;}
}
}
int main( void )
{pthread_t t1, t2, t3, t4;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);
}
?次執?結果:
thread 4 sells ticket:100
...
thread 4 sells ticket:1
thread 2 sells ticket:0
thread 1 sells ticket:-1
thread 3 sells ticket:-2
為什么只有100張票到0了的時候還有票能售出去呢?
這就是線程并發執行處理共享數據帶來的問題,在我處理最后一張票的時候其他線程也進來了他們看到的都是1此時他們還不知道這個票已經被其他線程給執行完了。如何解決這個問題呢?
代碼必須要有互斥行為:當代碼進入臨界區執行時不允許其他線程進入臨界區
互斥量的接口
初始化互斥量有兩種第
1 靜態分配
int pthread_mutex_destroy(pthread_mutex_t *mutex);
互斥量加鎖和解鎖
int pthread_mutex_lock(pthread_mutex_t *mutex);
int pthread_mutex_unlock(pthread_mutex_t *mutex);
返回值:成功返回0,失敗返回錯誤號
調用 pthread_lock是,可能會遇到以下情況
互斥量處于未上鎖狀態,該函數會講把互斥量鎖定返回成功
如何發起函數調用時,其他線程已鎖定互斥量,沒有競爭到互斥量資源,此時pthread_lock調用會陷入阻塞,直到互斥量解鎖
修該上面的售票代碼
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <sched.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(1000);
printf("%s sells ticket:%d\n", id, ticket);
ticket--;
pthread_mutex_unlock(&mutex);
// sched_yield(); 放棄CPU
}
else {
pthread_mutex_unlock(&mutex);
break;
}}}int main( void )
{
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);
pthread_mutex_destroy(&mutex);
}
1-3 互斥量的封裝
test_4_22_httpserve/Mutex.h · liu xi peng/linux---ubuntu系統 - 碼云 - 開源中國
大家有興趣的可以點進去看一下
2.線程同步
2-1 條件變量
當一個線程互斥地訪問某個變量時,他可能發現在其他線程狀態改變之前他什么也做不了
例如?個線程訪問隊列時,發現隊列為空,它只能等待,只到其它線程將?個節點添加到隊列
2-2 同步概念與競態條件
2-3 條件變量函數
初始化
#include <iostream>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
void *active( void *arg )
{
std::string name = static_cast<const char*>(arg);
while (true){
pthread_mutex_lock(&mutex);
pthread_cond_wait(&cond, &mutex);
std::cout << name << " 活動..." << std::endl;
pthread_mutex_unlock(&mutex);
}
}
int main( void )
{
pthread_t t1, t2;
pthread_create(&t1, NULL, active, (void*)"thread-1");
pthread_create(&t2, NULL, active, (void*)"thread-2");
sleep(3); // 可有可?,這?確保兩個線程已經在運?
while(true)
{
// 對?測試
// pthread_cond_signal(&cond); // 喚醒?個線程
pthread_cond_broadcast(&cond); // 喚醒所有線程
sleep(1);
}pthread_join(t1, NULL);
pthread_join(t2, NULL);
}
運行結果:
由線程來承擔消費者和生產者,線程可有多個,通常有一個特定的數據結構提供的緩沖區這個緩存區通常被成為交易場所