目录
一,线程的相关知识
1,线程的概念
每个进程都是独⽴的私有的空间,是⼀个独⽴的任务,虽然可能多个进程相 互之间需要协同⼯作,但需要系统⾃⼰的对进程间进行切换,因此在进程的上下⽂切换时,系统开销⽐较⼤ 为了提高系统的性能,在操作系统中引⼊了轻量级的进程,也叫做线程。
线程包含在进程内,每条线程都是进程中单一顺序的控制流,一个进程可以并发多条线程,且每个线程执行不同的任务。线程之间的资源是共享的。
2,多线程的概念
在一个程序中,存在许多费时的操作,如果使用单线程,程序只能顺序执行,只有等待当前操作完成后才能执行下一操作,造成资源浪费,影响执行效率,使用多线程就可以将耗时的操作任务放在后台工作,且同时执行其他操作,从而提高工作效率。
多线程就是指一个进程中同时有多个线程正在执行。
二,线程的操作
1,线程的创建
#include <pthread.h>
int pthread_create(pthread_t *thread, const pthread_attr_t*attr,void *(*start_routine) (void *),void *arg);
/*
返回值
成功:返回0;
失败:返回错误码
*/
/*
参数1:
pthread_t *thread:指针,地址,(存储线程id)创建线程后会把线程id存储到这个地址中。
参数2:
const pthread_attr_t *attr:要执⾏的线程的属性,传递的是属性变量值的地址,通常 写 NULL 表⽰使⽤默认属性创建线程。
参数3:
void *(*start_routine) (void *):函数指针,函数地址,线程执⾏的起始函数,线程从哪个函数开始执⾏
参数4:
void *arg:提供给参数3这个函数的参数。
*/
2,线程的关闭
结束当前线程,同时把线程结束状态,返回给创建当前线程的进程或线程 中。
#include <pthread.h>
void pthread_exit(void *retval);
/*
参数:
void *retval:指针,地址,作为线程的结束状态,返回给创建的线程中。
*/
3,线程的等待
等待线程结束,并接收线程结束的状态。
#include <pthread.h>
int pthread_join(pthread_t thread, void **retval);
/*
返回值:
成功:0;
失败:错误码;
*/
/*
参数1:
pthread_t thread:要等待结束的线程id
参数2:
void **retval:⼆级指针,⼀级指针的地址,把线程结束状态(⼀级指针),存储到这个地址中。
*/
4,线程的取消
取消指定线程的执行。
#include <pthread.h>
int pthread_cancel(pthread_t thread);
/*
参数:
pthread_t thread:线程的编号。
*/
三,线程间的同步互斥
1,基本概念
互斥:在同一时刻,有且只有一个任务访问一个资源
同步:在互斥的基础上,访问有着一定的先后顺序,由信号量完成。
信号量:一个非负整数,代表着一类资源。被用来控制对公共资源的访问。编程时可根据操作信号量值的结果判断是否对公共资源具有访问的权限,当信号量值大于0时,则可以访问,否则将阻塞。PV操作即对信号量的操作,-次P操作使信号量减1, - -次V操作使信号量加1。
注:当信号量用于同步时,需要多个信号量同时工作,而用于互斥时只需一个信号量即可。
P操作:(申请资源)只有当信号量大于0时,任务才能进行,否则,任务阻塞。
v操作:(释放资源)
2,(同步)信号量允许的三个操作
2.1,初始化
#include <semaphore.h>
int sem_init(sem_t *sem, int pshared, unsigned int value);
/*
参数1:
sem_t *sem:地址,信号量的地址,把初始化的值存⼊这个变量地址中
参数2:
int pshared:信号量使⽤的范围 0:表⽰在线程间使⽤;⾮0:表⽰在进程间使⽤。
参数3:
unsigned int value:信号量初始化的值
*/
/*
返回值:
成功:返回0
失败:返回-1
*/
2.2,p操作
资源信号量 减减,但sem==0就不能继续 减减 ⽽是阻塞等待
#include <semaphore.h>
int sem_wait(sem_t *sem);
2.3,v操作
#include <semaphore.h>
int sem_post(sem_t *sem);
举例:
#include<stdio.h>
#include<pthread.h>
#include<stdlib.h>
#include<unistd.h>
#include<semaphore.h>
int num;
sem_t rw;
void * thread_write(void * arg) //写
{
int i = *(int *)arg;
while(i--)
{
num = i;
sem_post(&rw); //p操作
sleep(2);
}
return NULL;
}
void * thread_read(void * arg) //读
{
while(1)
{
sem_wait(&rw); //v操作
printf("num==%d\n",num);
}
return NULL;
}
int main()
{
pthread_t tid1,tid2;
sem_init(&rw,0,5); //初始化
int n=10;
pthread_create(&tid1,NULL,thread_write,&n);
pthread_create(&tid2,NULL,thread_read,NULL);
exit(0);
}
3,互斥
互斥锁:就是每个线程在⾃⼰线程中访问资源,当能够获取到锁(加锁)时就访 问,访问完就释放锁(解锁)。当线程⽆法获得锁时,就阻塞等待直到获得锁为 ⽌。
注:加锁后一定要记得解锁。
3.1,互斥锁的初始化
初始化互斥锁,设置互斥锁变量
#include <pthread.h>
int pthread_mutex_init(pthread_mutex_t * mutex,constpthread_mutexattr_t * attr);
/*
参数1:
pthread_mutex_t * mutex:互斥锁变量地址,要初始化的互斥锁变量
参数2:
pthread_mutexattr_t * attr:互斥锁的属性,NULL表⽰默认属性
返回值:
成功:返回0
失败:返回-1
*/</