網站首頁 編程語言 正文
互斥鎖
使用互斥量完成對臨界區的資源的加鎖操作,使得同一時刻,對一個共享數據的使用只能又一個線程完成
例向屏幕上一次打印abcd四個字母
可以使用的是一個類似鎖連的思想 a 加完解開后拿b鎖依次類推
#define THRNUM 4
static pthread_mutex_t mut[4];
static int next(int n)
{
if(n + 1 == THRNUM)
return 0;
return n+1;
}
static void* pthreadfunc(void* p)
{
int n =(int)p;
char c = 'a' + (int)p;
while(1)
{
pthread_mutex_lock(mut + n);
write(1,&c,1);
pthread_mutex_unlock(mut + next(n));
}
pthread_exit(NULL);
}
int main()
{
int i,err;
pthread_t tid[THRNUM];
//創建線程
for(i = 0 ; i < THRNUM ;i++){
//初始化鎖
pthread_mutex_init(mut + i,NULL);
//加鎖
pthread_mutex_lock(mut+i );
err = pthread_create(tid+i,NULL,pthreadfunc,(void*)i );
if(err != 0)
{
fprintf(stderr,"create:%s\n",strerror(err));
exit(1);
}
}
//回收線程
pthread_mutex_unlock(mut + 0);
alarm(5);
for(i = 0 ; i < THRNUM ;i++){
pthread_join(tid+i,NULL);
}
}
條件變量
條件變量并不是鎖而是一種阻塞機制,使得我們的程序在某些特定的條件,比如生產者生產達到上限未消費,此時使用條件變量(加上while對條件的判斷)來阻塞生產,讓生產者消費
#include<stdio.h>
#include<unistd.h>
#include<pthread.h>
#include<stdlib.h>
#include<string.h>
int begnum=0;
static pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
typedef struct _prodinfo
{
int num;
struct _prodinfo *next;
}prod;
struct _prodinfo* head=NULL;
/* 條件變量可以引起阻塞并非鎖
*/
void *thr_produce(void*arg)
{
while(1)
{
prod* pd = malloc(sizeof(struct _prodinfo));
pd->num=begnum++;
pthread_mutex_lock(&mut);
pd->next=head;
head=pd;
printf(" -%ld號線程生產%d產品\n",pthread_self(),pd->num);
pthread_mutex_unlock(&mut);
pthread_cond_signal(&cond);
sleep(rand()%4);
}
}
void* thr_con(void* arg)
{
prod* pro=NULL;
while(1)
{
pthread_mutex_lock(&mut);
while(head==NULL)
pthread_cond_wait(&cond,&mut);
pro = head;
head=head->next;
printf(" -%ld號線程消費%d產品\n",pthread_self(),pro->num);
pthread_mutex_unlock(&mut);
free(pro);
sleep(rand()%4);
}
}
int main()
{
pthread_t cid,pid;
int err1=pthread_create(&pid,NULL,thr_produce,NULL);
if(err1)
{
fprintf(stderr,"pthread_creat():%s\n",strerror(err1));
exit(1);
}
int err2=pthread_create(&cid,NULL,thr_con,NULL);
if(err2)
{
fprintf(stderr,"pthread_creat():%s\n",strerror(err1));
exit(1);
}
pthread_join(pid,NULL);
pthread_join(cid,NULL);
}
信號量
介紹以下信號量是進化版的互斥量,允許多個線程訪問共享資源與條件變量和互斥量類此的操作,在進程和線程中均可以使用
int sem_init(sem_t *sem, int pshared, unsigned int value);
int sem_destroy(sem_t *sem);
Link with -pthread.
sem為定義的信號量,傳出型參數
pshared
- 0 代表線程信號量
- 1 代表進程信號量
alue 為定義的信號量個數
int sem_wait(sem_t *sem);
int sem_trywait(sem_t *sem);
int sem_timedwait(sem_t *sem, const struct timespec *abs_timeout);
申請信號量,申請成功value–,當value為0 則阻塞
int sem_post(sem_t *sem);
釋放信號量value++
例 信號量實現生產者消費者模型
sem_t pro_sem,con_sem;
#define semcnt 5
int i=0;
int queue[semcnt];
int beginnum = 100;
void *thr_produce(void*arg)
{
while(1)
{
sem_wait(&pro_sem);//生產者申請資源 pro_sem每被占用一次--一次 當為0時則阻塞
printf("%ld 線程生產了 %d\n",pthread_self(),beginnum);
queue[(i++)%semcnt]= beginnum++;
sem_post(&con_sem);//為消費者的信號量釋放資源pro_sem每被釋放一次++一次
sleep(rand()%4);
}
return NULL;
}
void* thr_con(void* arg)
{
int i=0;
int num=0;
while(1)
{
sem_wait(&con_sem);
num = queue[(i++)%semcnt];
printf("%ld 線程消費了 %d\n",pthread_self(),num);
sem_post(&pro_sem);
sleep(rand()%3);
}
return NULL;
}
int main()
{
sem_init(&pro_sem,0,semcnt);
sem_init(&con_sem,0,0); //消費者初始默認沒有產品
pthread_t tid[2];
int err1=pthread_create(&tid[0],NULL,thr_produce,NULL);
if(err1)
{
fprintf(stderr,"pthread_creat():%s\n",strerror(err1));
exit(1);
}
int err2=pthread_create(&tid[1],NULL,thr_con,NULL);
if(err2)
{
fprintf(stderr,"pthread_creat():%s\n",strerror(err1));
exit(1);
}
pthread_join(tid[0],NULL);
pthread_join(tid[1],NULL);
sem_destroy(&pro_sem);
sem_destroy(&con_sem);
}
讀寫鎖
讀寫鎖 與互斥量類似,但是讀寫鎖允許更高的并行性,其特性為:寫獨占,讀共享
讀寫鎖實質上是一把鎖,有不同的狀態,寫鎖的優先級高
讀寫鎖的三種狀態
- 讀模式下加鎖(讀鎖)
- 寫模式下加鎖(寫鎖)
- 不加鎖狀態
讀寫鎖的特性: 讀鎖可以共享讀的狀態,當讀鎖加上時,阻塞寫鎖的加鎖
即使讀鎖加上時 后面的 寫鎖依然會被阻塞,當前面讀鎖釋放時才能加成功
pthread_rwlock_t rwlock =PTHREAD_RWLOCK_INITIALIZER;
int beginum=100;
void*thr_Wr(void*arg)
{
while(1)
{
pthread_rwlock_wrlock(&rwlock);
printf("-寫線程--beginum = %d\n",beginum++);
usleep(2000);//模擬占用時間
pthread_rwlock_unlock(&rwlock);
usleep(2000);//簡單防止再搶鎖的方法但不建議使用
}
return NULL;
}
void*thr_ead(void*arg)
{
while (1)
{
pthread_rwlock_rdlock(&rwlock);
printf("-讀讀線程--beginum = %d\n",beginum);
usleep(2000);//模擬占用時間
pthread_rwlock_unlock(&rwlock);
usleep(2000);//簡單防止再搶鎖的方法但不建議使用
}
return NULL;
}
int main()
{
int n=8,i=0;
pthread_t tid[8];
for(i = 0; i<5;i++)
{
pthread_create(&tid[i],NULL,thr_ead,NULL);
}
for(; i<8;i++)
{
pthread_create(&tid[i],NULL,thr_Wr,NULL);
}
for(i = 0; i<8;i++)
{
pthread_join(tid[i],NULL);
}
pthread_rwlock_destroy(&rwlock);
}
原文鏈接:https://blog.csdn.net/m0_63515013/article/details/124618162
相關推薦
- 2022-07-13 kafka中Topic、消費組以及消息狀態詳解
- 2022-05-11 Spring數據源及注解開發
- 2022-03-29 深入了解Python并發編程_python
- 2022-12-31 React實現合成事件的源碼分析_React
- 2022-07-13 交換單鏈表第n和n+1個鏈點
- 2023-03-18 ASP.NET?Core?7?Razor?Pages項目發布到IIS的詳細過程_實用技巧
- 2023-03-02 C++回溯算法之深度優先搜索詳細介紹_C 語言
- 2022-09-04 Python裝飾器有哪些絕妙的用法_python
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支