2023/6/22 线程的使用,基础知识,总结复习,后续慢慢补充
特点
- Linux同样用task_struct来描述一个线程,线程和进程都参与统一调度
- 线程共享该进程的地址空间
- 线程是系统调度的最小单位,进程是资源分配的最小单位。
- 线程通信简单,全局变量可以实现,但是需要考虑临界资源保护问题
基础函数接口
1、 int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine) (void *), void *arg);
2、int pthread_exit(void *value_ptr) //结束线程
3、int pthread_join(pthread_t thread, void **value_ptr) //回收线程
//阻塞函数,等待一个指定的线程结束 value_ptr:指针*value_ptr指向线程返回的参数
4、pthread_t pthread_self(void); //获取线程号
5、int pthread_detach(pthread_t thread); //让线程分离,线程退出让系统自动回收线程资源
线程的补充函数接口
线程同步
通过信号量实现线程同步,同步就是多个任务(线程)按照约定的顺序相互配合完成一件事。这里面涉及了PV操作
P操作当信号量的值大于0时,可以申请资源,申请后,信号量减少1,如果为0就没法执行P操作,这时会阻塞V操作不阻塞,信号量增加1
1、//初始化信号量
int sem_init(sem_t *sem, int pshared, unsigned int value) //sem信号量对象,int 0为线程,1为进程间可以使用
int sem_wait(sem_t *sem) //申请资源,P操作
int sem_post(sem_t *sem) //释放资源 V操作
线程互斥
作用:多个线程访问临界资源时,使一次仅允许一个线程使用资源。
加入互斥锁
实现功能,每个临界资源都由一个互斥锁来保护,线程必须要线获得互斥锁才能访问临界资源,访问资源后释放该锁。如果无法获得锁,线程会阻塞直到获得锁为止。
补充概念:死锁是指两个或两个以上的进程/线程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去
死锁产生的四个必要条件:
1、互斥使用,即当资源被一个线程使用(占有)时,别的线程不能使用
2、不可抢占,资源请求者不能强制从资源占有者手中夺取资源,资源只能由资源占有者主动释放。
3、请求和保持,即当资源请求者在请求其他的资源的同时保持对原有资源的占有。
4、循环等待,即存在一个等待队列:P1占有P2的资源,P2占有P3的资源,P3占有P1的资源。这样就形成了一个等待环路。
注意:当上述四个条件都成立的时候,便形成死锁。当然,死锁的情况下如果打破上述任何一个条件,便可让死锁消失。
1、int pthread_mutex_init(pthread_mutex_t *mutex, pthread_mutexattr_t *attr) //atter为NULL为缺省
2、int pthread_mutex_lock(pthread_mutex_t *mutex) //申请互斥锁 阻塞
3、int pthread_mutex_trylock(pthread_mutex_t *mutex) //申请互斥锁,非阻塞
4、int pthread_mutex_unlock(pthread_mutex_t *mutex) //释放互斥锁
5、int pthread_mutex_destroy(pthread_mutex_t *mutex) //销毁互斥锁
功能代码
线程的创建与回收
#include <stdio.h>
#include <pthread.h>
#include <string.h>
#include <unistd.h>
char buf[32] = "";
//线程函数
void *handler(void *arg)
{
sleep(1);
printf("in the thread\n");
printf("num:%d\n", *((int *)arg));
printf("buf:%s\n", buf);
pthread_exit(NULL); //结束线程
}
int main(int argc, char const *argv[])
{
pthread_t tid;
int num = 100;//给线程传值的
if(pthread_create(&tid, NULL, handler, &num) != 0)
{
perror("create thread err");
return -1;
}
printf("in the main\n");
printf("main tid:%lu\n", pthread_self());
strcpy(buf, "hello");//全局变量直接通信
//线程回收,阻塞函数,等待子线程结束,回收线程资源
pthread_join(tid, NULL);
return 0;
}
根据标志位读输入打印输出
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <unistd.h>
char buf[32]="";
int local=0;
int main()
{
pthread_t tid;
if(pthread_create(&tid,NULL,add,NULL)!=0)
{
perror("per");
return -1;
}
while(1)
{
if(local==0)
{
fgets(buf,32,stdin);
local=1;
if(strcmp(buf,"quit")==0)
{
break;
}
}
}
pthread_join(tid,NULL);
}
void *add(void *a)
{
while(1)
{
if(local==1)
{
if(strcmp(buf,"quit")==0)
{
break;
}
printf("%s\n",buf);
local=0;
memset(buf,0,32);
}
}
}
线程同步2个信号量的PV操作
#include <stdio.h>
#include <pthread.h>
#include <string.h>
#include <semaphore.h>
char buf[32] = "";
sem_t sem, sem1;
void *print(void *arg)
{
while (1)
{
//P操作:申请资源,-1
sem_wait(&sem);
if (strcmp(buf, "quit") == 0)
break;
printf("buf:%s\n", buf);
sem_post(&sem1);
}
}
int main(int argc, char const *argv[])
{
pthread_t tid;
if (pthread_create(&tid, NULL, print, NULL) != 0)
{
perror("create thread err");
return -1;
}
if(sem_init(&sem, 0, 0) < 0)
{
perror("sem init err");
return -1;
}
if(sem_init(&sem1, 0, 1) < 0)
{
perror("sem init err");
return -1;
}
while (1)
{
//申请
sem_wait(&sem1);
printf("请输入:");
scanf("%s", buf);
//V操作:释放资源, +1
sem_post(&sem);
if (strcmp(buf, "quit") == 0)
break;
}
pthread_join(tid, NULL);
return 0;
}
使用互斥锁打印数组中元素
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
int a[10] = {0,1,2,3,4,5,6,7,8,9};
pthread_mutex_t lock;
void *print_handler(void *arg)
{
while(1)
{
pthread_mutex_lock(&lock);
for(int i = 0; i < 10; i++)
printf("%d", a[i]);
printf("\n");
pthread_mutex_unlock(&lock);
sleep(1);
}
}
void *swap_handler(void *arg)
{
int t;
while(1)
{
pthread_mutex_lock(&lock);
for(int i = 0; i < 5; i++)
{
t = a[i];
a[i] = a[9-i];
a[9-i] = t;
}
pthread_mutex_unlock(&lock);
}
}
int main(int argc, char const *argv[])
{
pthread_t t1, t2;
pthread_create(&t1, NULL, print_handler, NULL);
pthread_create(&t2, NULL, swap_handler, NULL);
if(pthread_mutex_init(&lock, NULL) != 0)
{
perror("mutex init err");
return -1;
}
pthread_join(t1, NULL);
pthread_join(t2, NULL);
return 0;
}
标签:复习,int,mutex,pthread,线程,sem,NULL
From: https://www.cnblogs.com/moveddown/p/17497596.html