嵌入式技术笔记(十七):线程同步

线程同步:互斥锁,线程信号量,条件变量

1. 互斥锁

1、定义互斥锁(变量) pthread_mutex_t mutex;
2、初始化锁:预设互斥锁的初始值
pthread_mutex_mutex = PTHREAD_MUTEX_INITIALIZER(不常用)
int pthread_mutex_init(pthread_mutex_t *restrict mutex,const pthread mutexattr_t *restrict attr)

  • 功能:初始化定义的互斥锁(就是设置互斥锁)
  • 返回值:总是返回0。所以这个函数不需要进程错误处理。
  • 参数:
    mutex:互斥锁,需要自己定义
    3、加锁解锁
    pthread_mutex_lock(&mutex);(阻塞加锁)访问临界区加锁操作
    pthread_mutex_trylock();(非阻塞加锁)当锁被占用时返回EBUSY而不是挂起等待
    pthread_mutex_unlock(&mutex); 访问临界区解锁
    4、进程退出时销毁互斥锁

2. 线程信号量

1. 线程信号量使用步骤:
1、定义信号量集合
sem_t sem[3]
线程信号量集合其实就是一个数组,数组每个元素就是一个信号量
sem[0]:第一个信号量
sem[1]:第二个信号量
sem[2]:第三个信号量

2、初始化集合中的每个信号量
#include <semaphore.h>
int sem_init(sem_t *sem, int pthread, unsigned int value)

  • 功能:初始化线程信号量集合中的某个信号量,给它一个初值
  • 返回值:成功返回0,失败返回-1,errno被设置
    信号量的错误号不是返回的,而是直接设置到errno
  • value:初始化值(对于二进制信号量来说,要么是1,要么是0)
  • pshared:0:给线程使用,!0可以给进程使用(!0不稳定,所以不给线程使用)

3、p、v操作

  • p操作
    #include <semaphore.h>
    int sem_wait(sem_t *sem);
    int sem_trywait(sem_t *sem);
    int sem_timedwait(sem_t *sem, const struct timespec *abs_timeout);
  • v操作
    #include <semaphore.h>
    int sem_post(sem_t *sem);
  • sem_wait value
    假如你获得的时候别人已经获得了这个信号量(value值减一),你阻塞
  • 练习1:线程1输出11111,线程2输出22222,线程3输出33333
    输出格式如下:
    11111
    22222
    33333
    11111

代码如下:

#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>

sem_t sem[3];

void *thread1(void *arg)
{
    while(1)
    {
        sem_wait(&sem[0]);
        printf("11111\n");
	sleep(1);
        sem_post(&sem[1]);
    }
}

void *thread2(void *arg)
{
    while(1)
    {
	sem_wait(&sem[1]);
	printf("22222\n");
	sleep(1);
	sem_post(&sem[2]);
    }
}

void *thread3(void *arg)
{
    while(1)
    {
	sem_wait(&sem[2]);
	printf("33333\n");
	sleep(1);
	sem_post(&sem[0]);
    }
}

int main()
{
    pthread_t id1, id2, id3;

    sem_init(&sem[0], 0, 1);
    sem_init(&sem[1], 0, 0);
    sem_init(&sem[2], 0, 0);

    if(pthread_create(&id1, NULL, thread1, NULL) != 0)
    {
	perror("thread create error!");
	exit(1);
    }

    if(pthread_create(&id2, NULL, thread2, NULL) != 0)
    {
	perror("thread create error!");
	exit(1);
    }

    if(pthread_create(&id3, NULL, thread3, NULL) != 0)
    {
	perror("thread create error!");
	exit(1);
    }

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

    sem_destroy(&sem[0]);
    sem_destroy(&sem[1]);
    sem_destroy(&sem[2]);

    return 0;
}

运行结果如下:
在这里插入图片描述

4、进程结束时,删除线程信号量集合

3. 条件变量(和互斥锁配合使用)

  • 练习2:一条线程做自加,一条线程输出(当自加变量到5输出之后自加变量清零)
    代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>

int count = 0;
pthread_mutex_t mutex;
pthread_cond_t cond;

void *add_1(void *arg)
{
    while(1)
    {
	pthread_mutex_lock(&mutex);
	count++;
	if(count == 5)
	{
	    pthread_cond_signal(&cond);
	}
	sleep(1);
	pthread_mutex_unlock(&mutex);
	sleep(1);
    }
}

void *print(void *arg)
{
    while(1)
    {
	pthread_mutex_lock(&mutex);
	if(count != 5)
	{
	    pthread_cond_wait(&cond, &mutex); 
	}
	printf("count = %d\n", count);
	count = 0;
	sleep(1);
	pthread_mutex_unlock(&mutex);
	sleep(1);
    }
}
int main()
{
    pthread_t id1;
    pthread_t id2;

    pthread_mutex_init(&mutex, NULL);
    pthread_cond_init(&cond, NULL);

    int ret1 = pthread_create(&id1, NULL, add_1, NULL);
    if(ret1 != 0)
    {
	perror("thread create error!");
	exit(0);
    } 
    
    int ret2 = pthread_create(&id2, NULL, print, NULL);
    if(ret2 != 0)
    {
	perror("thread create error!");
	exit(0);
    }

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

    return 0;
}

运行结果如下:
练习2

  • 条件变量的主要作用(线程协同):主线程对count+1,次线程发现当count==5时输出count的值并将count清零。
    多线程配合工作时,当线程检测到某条件不满足时就休眠,直到别的线程将条件准备好,然后通过条件变量将其叫醒
  • 使用步骤:
    1、定义一个条件变量
    pthread_cond_t
    2、初始化
    pthread_cond_init(pthread_cond_t *restrict cond, const pthread_condattr_t *restrict attr);
    功能:初始化条件变量,与互斥锁初始化类似
    pthread_cond_t cond = PTHREAD COND INITIALIZER;
    返回值:成功返回0,不成功返回非零错误号
    参数:
    cond:条件变量
    attr:属性,一般是NULL
    3、使用条件变量
    4、删除条件变量,也需要把互斥锁删除
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值