嵌入式笔记19 线程同步 线程信号量 条件变量

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


一、线程同步

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

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、进程退出时销毁互斥锁

#include<stdio.h>
#include<pthread.h>
#include<unistd.h>
#include<stdlib.h>
#include<string.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>

#define MAX_SIZE 1024

char buffer[MAX_SIZE];
struct message
{
    int fd;
    //pthread_mutex_t mutex;
};

pthread_mutex_t mutex;
//定义一个互斥锁
void *thread1(void *arg)
{
    struct message msg = *((struct message *)arg);
    int fd = msg.fd;
   
    
    while(1)
    {
    pthread_mutex_lock(&mutex);
	write(fd,"hello",5);
	write(fd,"world\n",6);
	//sleep(2);
	pthread_mutex_unlock(&mutex);
    }


}

void *thread2(void *arg)
{
    struct message msg = *((struct message *)arg);
    int fd = msg.fd;
    
    while(1)
    {
	pthread_mutex_lock(&mutex);
	write(fd, "hhhhh", 5);
	write(fd, "wwwww\n", 6);
	//sleep(2);
	pthread_mutex_unlock(&mutex);
    }


}



int main()
{
    pthread_t id1;

    struct message msg;

    

    int fd = open("./text.txt",O_RDWR|O_CREAT|O_APPEND, 0644);
    if(fd < 0)
    {
	perror("open file error!");
	exit(1);
    
    }
    msg.fd = fd;
    pthread_mutex_init(&mutex, NULL);
    //预设互斥锁的初始值
    if(pthread_create(&id1, NULL, thread1,(void *)(&msg) ) != 0)
    {
	perror("pthread_create error!\n");
	exit(1);
    
    }

     pthread_t id2;

    if(pthread_create(&id2, NULL, thread2, (void *)(&msg)) != 0)
    {
	perror("pthread_create error!\n");
	exit(1);

    }
    sleep(2);

    pthread_cancel(id2);
    pause();

    return 0;
}

二、线程信号量

1.线程信号量使用步骤

1、定义信号量集
sem_t sem [3]
线程信号量集合其实就是一个数组,数组中每一个元素就是一个信号量
(sem[0]:第一个信号量
sem[1]:第二个信号量
sem[2]:第三个信号量)
2、初始化集合中的每个信号量

man手册查看 在这里插入图片描述

头文件

#include<semaphore.h>

函数原型

int sem_init(sem_t *sem,int pthread,unsigned int value)

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

3、p、v操作
P操作:
int sem_wait(sem_t *sem);
int sem_trywait(sem_t *sem);
int sem_timedwait(sem_t *sem, const struct timespec *abs_timeout);
V操作:
int sem_post(sem_t *sem);
sem_wait value
假若你获得的时候被人已经获得了这个信号量(value值减一(在内核里加减)),你阻塞

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

#include<stdio.h>
#include<pthread.h>
#include<unistd.h>
#include<stdlib.h>
#include<string.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>

#define MAX_SIZE 1024

char buffer[MAX_SIZE];
struct message
{
    int fd;
    //pthread_mutex_t mutex;
};

pthread_mutex_t mutex;
sem_t sem[1];

void *thread1(void *arg)
{
    struct message msg = *((struct message *)arg);
    int fd = msg.fd;
   
    
    while(1)
    {
        //pthread_mutex_lock(&mutex);
	sem_wait(&sem[0]);
	write(fd,"hello",5);
	write(fd,"world\n",6);
	//sleep(2);
	//pthread_mutex_unlock(&mutex);
	sem_post(&sem[0]);
    }


}

void *thread2(void *arg)
{
    struct message msg = *((struct message *)arg);
    int fd = msg.fd;
    
    while(1)
    {
	sem_wait(&sem[0]);
	//pthread_mutex_lock(&mutex);
	write(fd, "hhhhh", 5);
	write(fd, "wwwww\n", 6);
	//sleep(2);
	//pthread_mutex_unlock(&mutex);
	sem_post(&sem[0]);
    }


}



int main()
{
    pthread_t id1;

    struct message msg;

    

    int fd = open("./text.txt",O_RDWR|O_CREAT|O_APPEND, 0644);
    if(fd < 0)
    {
	perror("open file error!");
	exit(1);
    
    }
    msg.fd = fd;
    pthread_mutex_init(&mutex, NULL);
    sem_init(&sem, 0, 1);


    if(pthread_create(&id1, NULL, thread1,(void *)(&msg) ) != 0)
    {
	perror("pthread_create error!\n");
	exit(1);
    
    }

     pthread_t id2;

    if(pthread_create(&id2, NULL, thread2, (void *)(&msg)) != 0)
    {
	perror("pthread_create error!\n");
	exit(1);

    }
    sleep(2);

    pthread_cancel(id2);
    pause();

    return 0;
}

练习:
线程1输出11111
线程2输出22222
线程3输出33333
11111
22222
33333
11111
22222
33333

条件变量(和互斥锁配和使用)
一条线程做自加,一条线程输出(当自加变量到5输出之后自加变量清零)

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

int count = 0;
pthread_mutex_t mutex;
void *add_1(void *arg)
{
    while(1)
    {
	pthread_mutex_lock(&mutex);
	count++;
	sleep(1);
	pthread_mutex_unlock(&mutex);
	sleep(1);
    }

}
void *print(void *arg)
{
    while(1)
    {
	pthread_mutex_lock(&mutex);
	if(count == 5)
	{
	    printf("%d\n",count);
	    count = 0;
	}
        sleep(1);
        pthread_mutex_unlock(&mutex);
	sleep(1);
    }


}

int main()
{
    pthread_t id1;
    pthread_t id2;

    int ret;
    pthread_mutex_init(&mutex, NULL);

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

    ret = pthread_create(&id2, NULL, print, NULL);
    if(ret != 0)
    {
	perror("thread create error!");
	exit(1);
    }
    pthread_join(id1, NULL);
    pthread_join(id2, NULL);
    return 0;
}

三、条件变量(和互斥锁配和使用)

条件变量的主要作用(线程协同):主线程对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、删除条件变量,也需要把互斥锁删除

#include<stdio.h>
#include<stdlib.h>
#include<pthread.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(&cont);
	}

	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);
	    count = 0;
	}
	printf("count = %d\n",count);
        sleep(1);
        pthread_mutex_unlock(&mutex);
	sleep(1);
    }


}

int main()
{
    pthread_t id1;
    pthread_t id2;

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

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

    ret = pthread_create(&id2, NULL, print, NULL);
    if(ret != 0)
    {
	perror("thread create error!");
	exit(1);
    }
    pthread_join(id1, NULL);
    pthread_join(id2, NULL);
    return 0;
}
/************************************************ * * The classic producer-consumer example. * Illustrates mutexes and conditions. * by Zou jian guo * 2003-12-22 * *************************************************/ #include #include #include #include "pthread.h" #define BUFFER_SIZE 16 /* Circular buffer of integers. */ struct prodcons { int buffer[BUFFER_SIZE]; /* the actual data */ pthread_mutex_t lock; /* mutex ensuring exclusive access to buffer */ int readpos, writepos; /* positions for reading and writing */ pthread_cond_t notempty; /* signaled when buffer is not empty */ pthread_cond_t notfull; /* signaled when buffer is not full */ }; /*--------------------------------------------------------*/ /* Initialize a buffer */ void init(struct prodcons * b) { pthread_mutex_init(&b->lock, NULL); pthread_cond_init(&b->notempty, NULL); pthread_cond_init(&b->notfull, NULL); b->readpos = 0; b->writepos = 0; } /*--------------------------------------------------------*/ /* Store an integer in the buffer */ void put(struct prodcons * b, int data) { pthread_mutex_lock(&b->lock); /* Wait until buffer is not full */ while ((b->writepos + 1) % BUFFER_SIZE == b->readpos) { printf("wait for not full\n"); pthread_cond_wait(&b->notfull, &b->lock); } /* Write the data and advance write pointer */ b->buffer[b->writepos] = data; b->writepos++; if (b->writepos >= BUFFER_SIZE) b->writepos = 0; /* Signal that the buffer is now not empty */ pthread_cond_signal(&b->notempty); pthread_mutex_unlock(&b->lock); } /*--------------------------------------------------------*/ /* Read and remove an integer from the buffer */ int get(struct prodcons * b) { int data; pthread_mutex_lock(&b->lock); /* Wait until buffer is not empty */ while (b->writepos == b->readpos) { printf("wait for not empty\n"); pthread_cond_wait(&b->notempty, &b->
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

qq_49181551

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值