系统编程学习笔记2——线程的同步互斥

        线程之间的资源是共享的

一、互斥锁

(一)逻辑

        不让线程自己私自访问共享资源

        在访问共享资源之前先判断是否有人在使用,有人使用则先等待,否则就使用

(二)代码

#include <stdio.h>

#include <string.h>

#include <stdlib.h>

#include <unistd.h>

#include <pthread.h>

int count = 100;

pthread_mutex_t mutex; //诞生一把全局锁

void *new_thread(void *arg)

{

        pthread_mutex_lock(&mutex); //上锁

        printf("线程上锁成功\n");

        if(count >= 100)

        {

                sleep(1);

                count -= 100;

        }

        pthread_mutex_unlock(&mutex); //解锁

        printf("线程解锁成功\n");

        return NULL;

}

int main(void)

{

        pthread_t tid; //创建线程

        int retval;

        pthread_mutex_init(&metex, NULL); //初始化互斥锁

        retval = pthread_creat(&tid, NULL, new_thread, NULL);

        if(retval != 0)

        {

                fprintf(stderr, "创建线程失败:%s\n", strerror(retval));

                return -1;

        }

       

        pthread_mutex_lock(&metex); //上锁

        printf("主线程上锁成功\n");

       

        if(count >= 100)

        {

                sleep(1);

                count -=100;

        }

        pthread_mutex_unlock(&metex); //解锁

        printf("主线程解锁成功\n");

       

        pthread_join(tid, NULL); //等待子线程介绍

       

        pthread_mutex_destroy(&mutex); //销毁互斥锁

        printf("count = %d\n", count);

       

        return 0;

}

二、读写锁

(一)特点

        可以A、B一起读取,但不可以A一边读、B一边写,也不可以A一边写、B也在一边写,即只要碰到写操作就会变成互斥锁  

(二)代码

#include <stdio.h>

#include <string.h>

#include <stdlib.h>

#include <unistd.h>

#include <pthread.h>

int count = 100;

pthread_rwlock_t rwlock; //诞生一把全局读写锁

void *read_thread(void *arg)

{
        int i = 5;

        pthread_rwlock_rdlock(&rwlock); //读锁

        while(i--)

        {
                sleep(1);

                printf("读线程:%s, count = %d\n", (char *)arg, count += 100);

        }

        pthread_rwlock_unlock(&rwlock); //解锁

}

void *write_thread(void *arg)

{
        int i = 5;

        pthread_rwlock_wrlock(&rwlock); //写锁

        while(i--)

        {

                sleep(1);

                printf("写线程:%s, count = %d\n", (char *)arg, count += 100);

        }

        pthread_rwlock_unlock(&rwlock); //解锁

}

int main(void)

{
        pthread_t tid[2]; //创建读、写线程

        int retval;

        pthread_rwlock_init(&rwlock, NULL); //初始化读写锁

        

        retval = pthread_create(tid, NULL, read_thread, "NO.1");

        if(retval != 0)

        {
                fprintf(stderr, "创建读线程失败:%s\n", strerror(retval));

                return -1;

        }

        retval = pthread_create(tid + 1, NULL, write_thread, "NO.2");

        if(retval != 0)

        {

                fprintf(stderr, "创建写线程失败:%s\n", strerror(retval));

                return -1;

        }

       

        pthread_join(tid[0], NULL); //等待读线程结束

        pthread_join(tid[1], NULL); //等待写线程结束

        pthread_rwlock_destroy(&rwlock); //销毁读写锁

        return 0;

}

三、条件变量

(一)使用规则

        必须配合互斥锁使用,是阻塞等待机制,若不符合判断条件就先休眠等待,反之则唤醒执行

(二)代码

#include <stdio.h>

#include <string.h>

#include <stdlib.h>

#include <unistd.h>

#include <pthread.h>

#include <string.h>

#include <signal.h>

int count=1000;

pthread_mutex_t mutex; //诞生一把全局锁

pthread_cond_t cond; //诞生一个条件变量

void *new_thread(void *arg)

{

        int retval;

        while(1)

        {

                pthread_mutex_lock(&mutex); //拿锁

                printf("%s线程拿锁成功\n", (char *)arg);

                while(count <100)

                {

                            printf("线程%s开始睡眠\n", (char *)arg);

                           

                            //解锁,等待被唤醒,被唤醒后再去拿锁

                            pthread_cond_wait(&cond, &mutex);

                            printf("线程%s醒来\n", (char *)arg);

                }

                count -= 100;

                sleep(1);

                printf("%s线程还锁成功,余额=%d\n", (char *)arg, count);

                pthread_mutex_unlock(&mutex);

        }

        return NULL;

}

void sighand(int signum)

{

        pthread_mutex_lock(&mutex);

        printf("充值\n");

        count+=1000;

        pthread_mutex_unlock(&mutex);

   

        //pthread_cond_signal(&cond); //唤醒一条线程

       pthread_cond_broadcast(&cond); //唤醒所有因指定条件变量睡眠的线程

}
 

int main(void)

{

        pthread_t tid[3];

        int retval;

   

        pthread_mutex_init(&mutex, NULL); //初始化互斥锁

        pthread_cond_init(&cond, NULL); //初始化条件变量

   

        retval = pthread_create(tid, NULL, new_thread, "1");

        if(retval != 0)

        {

                fprintf(stderr, "创建线程失败:%s\n", strerror(retval));

                return -1;

        }

   

        retval = pthread_create(tid+1, NULL, new_thread, "2");

        if(retval != 0)

        {

                fprintf(stderr, "创建线程失败:%s\n", strerror(retval));

                return -1;

        }

   

        retval = pthread_create(tid+2, NULL, new_thread, "3");

        if(retval != 0)

        {

                fprintf(stderr, "创建线程失败:%s\n", strerror(retval));

                return -1;

        }

   

        signal(SIGINT, sighand);

   

        pthread_join(tid[0], NULL);

        pthread_join(tid[1], NULL);

        pthread_join(tid[2], NULL);

   

        pthread_cond_destroy(&cond); //销毁条件变量

        pthread_mutex_destroy(&mutex); //销毁互斥锁

   

        printf("count=%d\n", count);
 

        return 0;

}

(三)适用场景

        需要线程等待某个条件符合才去运行,否则就休眠

四、信号量(匿名)

(一)作用        

        访问一个进程中的某块资源,判断是否存在这块资源

(二)常用函数

sem_init 初始化信号量

sem_wait P操作(减)

sem_post V操作(加)

sem_destroy 销毁信号量

(三)代码

#include <stdio.h>

#include <string.h>

#inlcude <stdlib.h>

#include <unistd.h>

#include <pthread.h>

#include <semaphore.h>

sem_t sem; //信号量

char buffer[100]; //缓冲区

void *new_thread(void *arg)

{

       while(1)

        {

                fgets(buffer, sizeof(buffer), stdin); //从键盘中读入一行数据到 buffer 中

                sem_post(&sem); //V操作

        }

        return NULL;

}

int main(void)

{

        pthread_t tid;

        int retval;

        sem_init(&sem, 0, 0);

        retval = pthread_create(&tid, NULL, new_thread, "faye");

        if(retval != 0)

        {

                fprintf(stderr, "创建线程失败:%s\n", strerror(retval));

                return -1;

        }

        while(1)

        {

                sem_wait(&sem); //P操作

                printf("buffer = %s\n", buffer);

        }

        pthread_join(tid, NULL);

        sem_destroy(&sem); //销毁信号量

        

        return 0;

}
        

  • 13
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值