C語言細(xì)致講解線程同步的集中方式
互斥鎖
使用互斥量完成對(duì)臨界區(qū)的資源的加鎖操作,使得同一時(shí)刻,對(duì)一個(gè)共享數(shù)據(jù)的使用只能又一個(gè)線程完成
例向屏幕上一次打印abcd四個(gè)字母
可以使用的是一個(gè)類似鎖連的思想 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];
//創(chuàng)建線程
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);
}
}條件變量
條件變量并不是鎖而是一種阻塞機(jī)制,使得我們的程序在某些特定的條件,比如生產(chǎn)者生產(chǎn)達(dá)到上限未消費(fèi),此時(shí)使用條件變量(加上while對(duì)條件的判斷)來阻塞生產(chǎn),讓生產(chǎn)者消費(fèi)
#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號(hào)線程生產(chǎn)%d產(chǎn)品\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號(hào)線程消費(fèi)%d產(chǎn)品\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);
}信號(hào)量
介紹以下信號(hào)量是進(jìn)化版的互斥量,允許多個(gè)線程訪問共享資源與條件變量和互斥量類此的操作,在進(jìn)程和線程中均可以使用
int sem_init(sem_t *sem, int pshared, unsigned int value); int sem_destroy(sem_t *sem); Link with -pthread.
sem為定義的信號(hào)量,傳出型參數(shù)
pshared
- 0 代表線程信號(hào)量
- 1 代表進(jìn)程信號(hào)量
alue 為定義的信號(hào)量個(gè)數(shù)
int sem_wait(sem_t *sem);
int sem_trywait(sem_t *sem);
int sem_timedwait(sem_t *sem, const struct timespec *abs_timeout);
申請(qǐng)信號(hào)量,申請(qǐng)成功value–,當(dāng)value為0 則阻塞
int sem_post(sem_t *sem);
釋放信號(hào)量value++
例 信號(hào)量實(shí)現(xiàn)生產(chǎn)者消費(fèi)者模型
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);//生產(chǎn)者申請(qǐng)資源 pro_sem每被占用一次--一次 當(dāng)為0時(shí)則阻塞
printf("%ld 線程生產(chǎn)了 %d\n",pthread_self(),beginnum);
queue[(i++)%semcnt]= beginnum++;
sem_post(&con_sem);//為消費(fèi)者的信號(hào)量釋放資源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 線程消費(fèi)了 %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); //消費(fèi)者初始默認(rèn)沒有產(chǎn)品
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);
}讀寫鎖
讀寫鎖 與互斥量類似,但是讀寫鎖允許更高的并行性,其特性為:寫?yīng)氄?,讀共享
讀寫鎖實(shí)質(zhì)上是一把鎖,有不同的狀態(tài),寫鎖的優(yōu)先級(jí)高
讀寫鎖的三種狀態(tài)
- 讀模式下加鎖(讀鎖)
- 寫模式下加鎖(寫鎖)
- 不加鎖狀態(tài)
讀寫鎖的特性: 讀鎖可以共享讀的狀態(tài),當(dāng)讀鎖加上時(shí),阻塞寫鎖的加鎖
即使讀鎖加上時(shí) 后面的 寫鎖依然會(huì)被阻塞,當(dāng)前面讀鎖釋放時(shí)才能加成功
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);//模擬占用時(shí)間
pthread_rwlock_unlock(&rwlock);
usleep(2000);//簡(jiǎn)單防止再搶鎖的方法但不建議使用
}
return NULL;
}
void*thr_ead(void*arg)
{
while (1)
{
pthread_rwlock_rdlock(&rwlock);
printf("-讀讀線程--beginum = %d\n",beginum);
usleep(2000);//模擬占用時(shí)間
pthread_rwlock_unlock(&rwlock);
usleep(2000);//簡(jiǎn)單防止再搶鎖的方法但不建議使用
}
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);
}到此這篇關(guān)于C語言細(xì)致講解線程同步的集中方式的文章就介紹到這了,更多相關(guān)C語言線程同步內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C++實(shí)現(xiàn)LeetCode(26.有序數(shù)組中去除重復(fù)項(xiàng))
這篇文章主要介紹了C++實(shí)現(xiàn)LeetCode(26.有序數(shù)組中去除重復(fù)項(xiàng)),本篇文章通過簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-07-07
VC++中HTControl控件類之CHTRichEdit富文本編輯控件實(shí)例
這篇文章主要介紹了VC++中HTControl控件類之CHTRichEdit富文本編輯控件,是一個(gè)比較實(shí)用的功能,需要的朋友可以參考下2014-08-08
C++ Qt開發(fā)之使用QHostInfo查詢主機(jī)地址
Qt 是一個(gè)跨平臺(tái)C++圖形界面開發(fā)庫,利用Qt可以快速開發(fā)跨平臺(tái)窗體應(yīng)用程序,本文將重點(diǎn)介紹如何運(yùn)用QHostInfo組件實(shí)現(xiàn)對(duì)主機(jī)地址查詢功能,希望對(duì)大家有所幫助2024-03-03

