线程分离、线程传参、线程互斥(互斥锁)、线程同步(信号量)

我要成为嵌入式高手之2月27日Linux高编第十天!!

学习笔记

一、线程分离属性

线程结束后自动回收线程空间

1、pthread_attr_init

#include <pthread.h>

int pthread_attr_init(pthread_attr_t *attr);

功能:线程属性初始化

2、pthread_attr_destroy

#include <pthread.h>

int pthread_attr_destroy(pthread_attr_t *attr);

功能:线程属性销毁

3、pthread_attr_setdetachstate

#include <pthread.h>

int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate);

功能:设置分离属性(自动回收)

参数:

        attr:pthread_attr_t 类型的参数的地址;

        detachstate:需要的设置的属性

                        PTHREAD_CREATE_DETACHED:分离属性(自动回收)

                        PTHREAD_CREATE_JOINABLE:加入属性(默认情况)

二、线程传参

线程传参练习

        定义一个学生结构体;创建两个线程,线程1负责从终端接收学生信息,线程2负责将学生信息打印在终端

#include "head.h"

struct stu
{
    char name[32];
    char sex;
    int age;
    int score;
}student;

void *thread1(void *arg)
{
    struct stu *student = arg;

    gets(student->name);
    student->sex = getchar();
    scanf("%d", &student->age);
    scanf("%d", &student->score);

    return NULL;
}

void *thread2(void *arg)
{
    struct stu *student = arg;
    sleep(10);

    printf("\nname:%s\n", student->name);
    printf("sex:%c\n", student->sex);
    printf("age:%d\n", student->age);
    printf("score:%d\n", student->score);

    return NULL;
}

int main(void)
{
    struct stu student;

    pthread_t tid1;
    pthread_t tid2;
    
    pthread_create(&tid1, NULL, thread1, &student);
    pthread_create(&tid2, NULL, thread2, &student);

    pthread_join(tid1, NULL);
    pthread_join(tid2, NULL);

    return 0;
}

  

三、线程互斥

1、互斥锁:防止资源竞争

产生资源竞争的原因:

多线程操作全局变量时最好都加锁

互斥锁只能解决资源竞争的问题,无法同步代码 (没有先后执行的顺序关系)

互斥锁有关的函数接口:

1)pthread_mutex_init:

int pthread_mutex_init(pthread_mutex_t *restrict mutex,
const pthread_mutexattr_t *restrict attr);
功能:
        互斥锁初始化
参数:
        mutex:互斥锁空间首地址
        attr:互斥锁的属性(默认为NULL)
返回值:
        成功返回0 
        失败返回错误码 

2)pthread_mutex_destroy

int pthread_mutex_destroy(pthread_mutex_t *mutex);
功能:
        互斥锁销毁
参数:
        mutex:互斥锁空间首地址
返回值:
        成功返回0 
        失败返回错误码

3)pthread_mutex_lock:

int pthread_mutex_lock(pthread_mutex_t *mutex);
功能:  上锁

4)pthread_mutex_unlock:

int pthread_mutex_unlock(pthread_mutex_t *mutex);
功能:  解锁

2、临界资源 / 临界区:

加锁解锁中间的代码称为临界资源/临界区;

同一时刻临界资源不能同时执行,只能执行其中一个临界资源代码。

3、原子操作:

CPU最小的一次不被任务调度打断的操作称为原子操作  

互斥锁的应用:

#include "head.h"

pthread_mutex_t lock;
int num = 0;

void *thread1(void *arg)
{
    while (1)
    {  
        pthread_mutex_lock(&lock);
        num = 100;
        pthread_mutex_unlock(&lock);
    }

    return NULL;
}

void *thread2(void *arg)
{
    while (1)
    {
        pthread_mutex_lock(&lock);
        num = 200;
        printf("%d\n", num);
        pthread_mutex_unlock(&lock);
    }

    return NULL;
}

int main(void)
{
    pthread_t tid1;
    pthread_t tid2;

    pthread_mutex_init(&lock, NULL);

    pthread_create(&tid1, NULL, thread1, NULL);
    pthread_create(&tid2, NULL, thread2, NULL);

    pthread_join(tid1, NULL);
    pthread_join(tid2, NULL);

    pthread_mutex_destroy(&lock);

    return 0;
}

4、死锁

1)概念

        多线程操作互斥锁,导致多个线程均无法向下执行的状态

2)死锁产生的四个必要条件:

        ①互斥条件

        ②不可剥夺条件

        ③请求保持

        ④循环等待

3)避免产生死锁

        1、pthread_mutex_trylock 替代 pthread_mutex_lock

        2、加锁顺序保持一致

四、信号量(semaphore)

信号量是一种资源,可与被申请(会被阻塞)释放(不会被阻塞)

P操作:申请资源

V操作:释放资源

通过对信号量的PV操作,实现线程的同步进行

1)sem_init

#include <semaphore.h>

int sem_init(sem_t *sem, int pshared, unsigned int value);

功能:初始化信号量

参数:

        sem:信号量空间首地址

        pshared:

                0一个进程间的所有线程共享

                非0,进程间共享

        value:初始化的值(资源量的个数)

返回值:成功0;失败-1

2)sem_destroy

#include <semaphore.h>

int sem_destroy(sem_t *sem);

功能:信号量的销毁

参数:sem:信号量空间的首地址

返回值:成功0;失败-1;

3)sem_wait

#include <semaphore.h>

int sem_wait(sem_t *sem);

功能:申请信号量

参数:信号量空间的首地址

4)sem_post

#include <semaphore.h>

int sem_post(sem_t *sem);

功能:释放信号量

参数:信号量空间的首地址

信号量的应用

#include "head.h"

char tmpbuff[4096] = {0};
sem_t sem_r;
sem_t sem_w;

void *thread1(void *arg)
{
    while (1)
    {
        sem_wait(&sem_w);
        gets(tmpbuff);
        sem_post(&sem_r);
    }

    return NULL;
}

void *thread2(void *arg)
{
    while (1)
    {
        sem_wait(&sem_r);
        printf("tmpbuff = %s\n", tmpbuff);
        sem_post(&sem_w);
    }

    return NULL;
}

int main(void)
{
    pthread_t tid1;
    pthread_t tid2;

    sem_init(&sem_w, 0, 1);
    sem_init(&sem_r, 0, 0);


    pthread_create(&tid1, NULL, thread1, NULL);
    pthread_create(&tid2, NULL, thread2, NULL);

    pthread_join(tid1, NULL);
    pthread_join(tid2, NULL);

    sem_destroy(&sem_w);
    sem_destroy(&sem_r);

    return 0;
}

  • 24
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值