并发程序设计--D8D9锁和条件变量

临界资源概念:

不能同时访问的资源,比如写文件,只能由一个线程写,同时写会写乱。

比如外设打印机,打印的时候只能由一个程序使用。

外设基本上都是不能共享的资源。

生活中比如卫生间,同一时间只能由一个人使用。

必要性: 临界资源不可以共享

man手册找不到 pthread_mutex_xxxxxxx (提示No manual entry for pthread_mutex_xxx)的解决方法:

    apt-get install manpages-posix-dev

互斥锁的创建和销毁

两种方法创建互斥锁,静态方式动态方式

动态方式:

int pthread_mutex_init(pthread_mutex_t *restrict mutex,const pthread_mutexattr_t *restrict attr);

其中mutexattr用于指定互斥锁属性,如果为NULL则使用缺省属性。

静态方式:

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

锁的销毁:

int pthread_mutex_destroy(pthread_mutex_t *mutex)

在Linux中,互斥锁并不占用任何资源,因此LinuxThreads中的 pthread_mutex_destroy()除了检查锁状态以外(锁定状态则返回EBUSY)没有其他动作。

互斥锁的使用:

int pthread_mutex_lock(pthread_mutex_t *mutex)

int pthread_mutex_unlock(pthread_mutex_t *mutex)

int pthread_mutex_trylock(pthread_mutex_t *mutex)

vim 设置代码全文格式化:gg=G

并发程序设计--D8D9锁和条件变量_第1张图片

 实现两个线程同时往一个文件中写内容

#include 
#include 
#include 
#include 

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;


FILE *fp;
void *func2(void *arg){
    pthread_detach(pthread_self());
    printf("This func2 thread\n");
    
    char str[]="I write func2 line\n";
    char c;
    int i=0;
    while(1){
        pthread_mutex_lock(&mutex);
        while(i

读写锁

必要性:提高线程执行效率

特性:

写者:写者使用写锁,如果当前没有读者,也没有其他写者,写者立即获得写锁;否则写者将等待,直到没有读者和写者。

读者:读者使用读锁,如果当前没有写者,读者立即获得读锁;否则读者等待,直到没有写者。

注意:

同一时刻只有一个线程可以获得写锁,同一时刻可以有多个线程获得读锁。

读写锁处于写锁状态时,所有试图对读写锁加锁的线程,不管是读者试图加读锁,还是写者试图加写锁,都会被阻塞。

读写锁处于读锁状态时,有写者试图加写锁时,之后的其他线程的读锁请求会被阻塞,以避免写者长时间的不写锁

初始化一个读写锁   pthread_rwlock_init

读锁定读写锁       pthread_rwlock_rdlock

非阻塞读锁定     pthread_rwlock_tryrdlock

写锁定读写锁      pthread_rwlock_wrlock

非阻塞写锁定      pthread_rwlock_trywrlock

解锁读写锁         pthread_rwlock_unlock

释放读写锁         pthread_rwlock_destroy

#include 
#include 
#include 
#include 


pthread_rwlock_t rwlock;

FILE *fp;
void * read_func(void *arg){
    pthread_detach(pthread_self());
    printf("read thread\n");
    char buf[32]={0};
    while(1){
        //rewind(fp);
        pthread_rwlock_rdlock(&rwlock);
        while(fgets(buf,32,fp)!=NULL){
            printf("%d,rd=%s\n",(int)arg,buf);
            usleep(1000);
        }
        pthread_rwlock_unlock(&rwlock);
        sleep(1);
    }

}



void *func2(void *arg){
    pthread_detach(pthread_self());
    printf("This func2 thread\n");
    
    char str[]="I write func2 line\n";
    char c;
    int i=0;
    while(1){
        pthread_rwlock_wrlock(&rwlock);
        while(i

死锁

概念:

避免方法:

  1. 锁越少越好,最好使用一把锁
  2. 调整好锁的顺序

条件变量

应用场景:生产者消费者问题,是线程同步的一种手段。

必要性:为了实现等待某个资源,让线程休眠。提高运行效率

资源非共享、资源不是随时随地就有,需要等待

int pthread_cond_wait(pthread_cond_t *restrict cond,

           pthread_mutex_t *restrict mutex);//等待资源

int pthread_cond_timedwait(pthread_cond_t *restrict cond,

           pthread_mutex_t *restrict mutex,

           const struct timespec *restrict abstime);//等待一定时间超时退出

int pthread_cond_signal(pthread_cond_t *cond);//放出信号,有资源了

int pthread_cond_broadcast(pthread_cond_t *cond);

使用步骤:

初始化:

静态初始化(条件变量和互斥量必须结合使用)

pthread_cond_t   cond = PTHREAD_COND_INITIALIZER;      //初始化条件变量

pthread_mutex_t  mutex = PTHREAD_MUTEX_INITIALIZER;  //初始化互斥量

或使用动态初始化

pthread_cond_init(&cond);

生产资源线程:

pthread_mutex_lock(&mutex);

开始产生资源

pthread_cond_sigal(&cond);    //通知一个消费线程

或者

pthread_cond_broadcast(&cond); //广播通知多个消费线程

pthread_mutex_unlock(&mutex);

消费者线程:

pthread_mutex_lock(&mutex);

while (如果没有资源){   //防止惊群效应

pthread_cond_wait(&cond, &mutex);

}

有资源了,消费资源

pthread_mutex_unlock(&mutex);  

注意:

1 pthread_cond_wait(&cond, &mutex),在没有资源等待是是先unlock 休眠,等资源到了,再lock

所以pthread_cond_wait 和 pthread_mutex_lock 必须配对使用。

并发程序设计--D8D9锁和条件变量_第2张图片

如果pthread_cond_signal或者pthread_cond_broadcast 早于 pthread_cond_wait ,则有可能会丢失信号。

3 pthead_cond_broadcast 信号会被多个线程收到,这叫线程的惊群效应。所以需要加上判断条件while循环。

#include 
#include 
#include 
#include 


pthread_cond_t  hasTaxi=PTHREAD_COND_INITIALIZER;
pthread_mutex_t lock  = PTHREAD_MUTEX_INITIALIZER;


struct taxi{
    struct taxi *next;
    int num;

};

struct taxi *Head=NULL;

void *taxiarv(void *arg){
    printf("taxi arrived thread\n");
    pthread_detach(pthread_self());
    struct taxi *tx;
    int i=1;
    while(1){
        tx = malloc(sizeof(struct taxi));
        tx->num = i++;
        printf("taxi %d comming\n",tx->num);
        pthread_mutex_lock(&lock);
        tx->next = Head;
        Head = tx;
        pthread_cond_signal(&hasTaxi);
        //pthread_cond_broadcast(&hasTaxi);
        pthread_mutex_unlock(&lock);
        sleep(1);
    }
    pthread_exit(0);
}

void *takeTaxi(void *arg){
    printf("take taxi thread\n");
    pthread_detach(pthread_self());
    struct taxi *tx;
    while(1){
        pthread_mutex_lock(&lock);
        while(Head==NULL)
        {
            pthread_cond_wait(&hasTaxi,&lock);
        }
        tx = Head;
        Head=tx->next;
        printf("%d,Take taxi %d\n",(int)arg,tx->num);
        free(tx);
        pthread_mutex_unlock(&lock);
    }
    pthread_exit(0);
}

int main(){
    pthread_t tid1,tid2,tid3;

    pthread_create(&tid1,NULL,taxiarv,NULL);
//    sleep(5);
    pthread_create(&tid2,NULL,takeTaxi,(void*)1);
    pthread_create(&tid2,NULL,takeTaxi,(void*)2);
    pthread_create(&tid2,NULL,takeTaxi,(void*)3);

    while(1) {
        sleep(1);

    }


}

你可能感兴趣的:(应用层,linux,服务器)