我要成为嵌入式高手之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;
}