线程的互斥和同步技术

概念

线程之间共享大量的内容,多线程在访问共享数据时,需要一些保护机制,避免造成数据混乱和错误。
常用互斥技术:互斥锁信号量
常用同步技术:条件变量

  • 互斥锁
    编程步骤:
    1)初始化互斥锁
    2)加锁
    3)访问共享资源
    4)解锁
    5)不再使用,销毁锁
    互斥锁实现:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>

char *data[5];//长度为5的字符串数组
int size = 0;//记录当前下标,数组中数据个数
//初始化
pthread_mutex_t lock;

//线程函数
void *task(void *arg)
{
    //2.加锁
    pthread_mutex_lock(&lock);
    //3.访问共享内存
    data[size] = (char *)arg;
    usleep(100000);
    size++;
    //4.解锁
    pthread_mutex_unlock(&lock);

    pthread_exit(NULL);
}

int main()
{
    pthread_t id1,id2;
    //1.声明
    pthread_mutex_init(&lock,NULL);

    data[size] = "liubie";
    size++;

    pthread_create(&id1,NULL,task,"guanyu");
    pthread_create(&id2,NULL,task,"zhaoyun");

    pthread_join(id1,NULL);
    pthread_join(id2,NULL);

    int i;
    for(i=0;i<size;i++)
        printf("%s\n",data[i]);

    //5.销毁锁
    pthread_mutex_destroy(&lock);

    return 0;
}
  • 无名信号量
    编程步骤:
    1)声明信号量
    2)初始化信号量的初始计数
    3)P操作
    4)访问共享资源
    5)V操作
    6)不再使用,删除信号量
    无名信号量实现:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>

char *data[5];//长度为5的字符串数组
int size = 0;//记录当前下标,数组中数据个数
//1.声明
sem_t sem;

//线程函数
void *task(void *arg)
{
    //3.P操作
    sem_wait(&sem);
    //4.访问共享内存
    data[size] = (char *)arg;
    usleep(100000);
    size++;
    //5.V操作
    sem_post(&sem);

    pthread_exit(NULL);
}

int main()
{
    pthread_t id1,id2;
    //2.初始化
    sem_init(&sem,0,1);

    data[size] = "liubie";
    size++;

    pthread_create(&id1,NULL,task,"guanyu");
    pthread_create(&id2,NULL,task,"zhaoyun");

    pthread_join(id1,NULL);
    pthread_join(id2,NULL);

    int i;
    for(i=0;i<size;i++)
        printf("%s\n",data[i]);

    //6.销毁
    sem_destroy(&sem);

    return 0;
}
  • 有名信号量
    编程步骤:
    1)声明信号量
    2)创建/打开有名信号量
    3)P操作
    4)访问共享资源
    5)V操作
    6)不再使用,删除信号量
    有名信号量实现
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <pthread.h>
#include <semaphore.h>

char *data[5];//长度为5的字符串数组
int size = 0;//记录当前下标,数组中数据个数
//1.声明信号量
sem_t *sem;

//线程函数
void *task(void *arg)
{
    //3.P操作
    sem_wait(sem);
    //4.访问共享内存
    data[size] = (char *)arg;
    usleep(100000);
    size++;
    //5.V操作
    sem_post(sem);

    pthread_exit(NULL);
}

int main()
{
    pthread_t id1,id2;
    //2.创建/打开有名信号量
    sem = sem_open("mysem",O_RDWR|O_CREAT|O_EXCL,0666,1);
    if(sem==SEM_FAILED){
        perror("sem_open");
        exit(0);
    }

    data[size] = "liubie";
    size++;

    pthread_create(&id1,NULL,task,"guanyu");
    pthread_create(&id2,NULL,task,"zhaoyun");

    pthread_join(id1,NULL);
    pthread_join(id2,NULL);

    int i;
    for(i=0;i<size;i++)
        printf("%s\n",data[i]);

    //6.销毁
    sem_close(sem);
    sem_unlink("mysem");

    return 0;
}
  • 条件变量(同步)
    编程接口:
    1)声明和初始化
    int pthread_cond_init(pthread_cond_t *restrict cond,const pthread_condattr_t *restrict attr);
    或者
    pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
    2)等待条件成立
    int pthread_cond_timedwait(pthread_cond_t *restrict cond,pthread_mutex_t *restrict mutex,const struct timespec *restrict abstime);
    int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex);
    3)唤醒等待条件的线程
    int pthread_cond_broadcast(pthread_cond_t *cond);
    int pthread_cond_signal(pthread_cond_t *cond);
    4)销毁
    int pthread_cond_destroy(pthread_cond_t *cond);
    条件变量实现
//条件变量(同步)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>

//1.声明
pthread_mutex_t lock;
pthread_cond_t cond;
char buf[100];

void *task1(void *arg)
{
    //等待之前先加锁
    pthread_mutex_lock(&lock);
    printf("线程1加锁成功!\n");
    sleep(1);
    //2.等待条件成立
    pthread_cond_wait(&cond,&lock);
    printf("线程1被条件唤醒!\n");
    
    //3.条件成立后执行内容
    printf("你的名字的长度为%d\n",strlen(buf));
    sleep(10);
    
    //4.条件成立代码执行完解锁
    printf("线程1解锁成功!\n");
    pthread_mutex_unlock(&lock);

    pthread_exit(NULL);
}

void *task2(void *arg)
{
    //等待之前先加锁
    pthread_mutex_lock(&lock);
    printf("线程2加锁成功!\n");
    sleep(1);
    //2.等待条件成立
    pthread_cond_wait(&cond,&lock);
    printf("线程2被条件唤醒!\n");
    
    //3.条件成立后执行内容
    printf("靓仔你的名字是%s\n",buf);
    sleep(10);

    //4.条件成立代码执行完解锁
    printf("线程2解锁成功!\n");
    pthread_mutex_unlock(&lock);

    pthread_exit(NULL);
}

void *task3(void *arg)
{
    sleep(10);
    //等待之前先加锁
    pthread_mutex_lock(&lock);
    printf("线程3加锁成功!\n");
    //2.等待条件成立
    pthread_cond_wait(&cond,&lock);
    printf("线程3被条件唤醒!\n");
    
    //3.条件成立后执行内容
    printf("靓仔你名字的第一个字符是%c\n",*buf);
    sleep(1);

    //4.条件成立代码执行完解锁
    printf("线程3解锁成功!\n");
    pthread_mutex_unlock(&lock);

    pthread_exit(NULL);
}

int main()
{
    pthread_t id1,id2,id3;
    //1.初始化
    pthread_cond_init(&cond,NULL);
    pthread_mutex_init(&lock,NULL);

    pthread_create(&id1,NULL,task1,NULL);
    pthread_create(&id2,NULL,task2,NULL);
    pthread_create(&id3,NULL,task3,NULL);

    printf("请输入你的名字:\n");
    fgets(buf,100,stdin);
    buf[strlen(buf)-1] = 0;
    
    //唤醒等待的线程
    //pthread_cond_signal(&cond);//唤醒一个
    pthread_cond_broadcast(&cond);//唤醒全部

    pthread_join(id1,NULL);
    pthread_join(id2,NULL);
    pthread_join(id3,NULL);

    //5.销毁
    pthread_cond_destroy(&cond);
    pthread_mutex_destroy(&lock);

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值