线程和进程
线程:是系统调度的基本单位
进程:是系统分配资源的基本单位
为了任务处理linux系统引入了进程的概念去实现多任务处理:
进程的特点:1.进程间的内存空间是互相独立的。
2.进程是系统分配资源的最少单位 -》每创建一个进程系统都会进行一次资源分配
3.因为进程间的空间的独立的,假如进程之间需要相互协作的话就必须,使用管道,
消息队列,信号,共享内存。。。等通信方式进程数据交换
如何使用线程?
注意编译线程时必须加入线程库: -lpthread
例子:gcc pthread.c -o pthread -lpthread
线程需要注意的事项:
1.在线程中,主线程死亡则所有子线程也会死亡!
2.子线程与主线程,共享数据段与堆空间,当全局变量与局部变量同门时,线程优先使用局部变量。(所以线程间的通信,只有使用全局变量即可)
3.线程是不会向操作系统申请资源的,他只会从主线程中拿到自己的虚拟栈 (大大的节省内存空间)
线程的使用:
1. pthread_create---》线程创建
头文件:
#include <pthread.h>
函数原型:
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine) (void *), void *arg);
参数一:pthread_t *thread -》线程PID。-》每一个线程他都有自己的一个唯一标识
参数二:线程属性 -》NULL 默认属性即可
参数三:重点!!!
void *(*start_routine) (void *) -》指针,指向一个函数 void * func(void *atg)
任务函数,类型必须为void * func(void *atg);
参数四:传递给任务函数的参数
2.pthread_join -- -》线程等待数
头文件:
#include <pthread.h>
函数原型:
int pthread_join(pthread_t thread, void **retval); -》回收线程的资源
参数一:等待的线程PID
参数二:保存线程的退出信息
返回值:成功返回0 失败返回一个错误号
3. pthread_detach ---》设置分离属性:-》一般线程创建后就马上设置为分离属性
int pthread_detach(pthread_t thread); 》假如线程设置为分离属性后,pthread_join函数就不会等待
参数一。线程PID
返回值:成功返回0,失败返回错误号
4.pthread_exit ---》线程退出函数
头文件:
#include <pthread.h>
函数原型:
void pthread_exit(void *retval);
参数一:把退出信息存放到该地址上,会传递给pthread_join的第二个参数
5. pthread_cancel --->线程取消函数:-》杀死线程
头文件:
#include <pthread.h>
函数原型:
int pthread_cancel(pthread_t thread);
参数一:要杀死的线程PID
成功:返回0 失败发回错误号
6. pthread_setcancelstate --->开启或关闭线程取消信号:
头文件:
#include <pthread.h>
函数原型:
int pthread_setcancelstate(int state, int *oldstate);
参数一:开启或关闭线程取消信号
开启 PTHREAD_CANCEL_ENABLE
关闭 PTHREAD_CANCEL_DISABLE
参数二:原来开启或关闭的状态
成功:返回0 失败返回错误号
------------------------------------------------------------------------------------------------------------------
练习:使用线程函数
#include <stdio.h>
#include <pthread.h>
int i=100;
void *func(void *arg)
{
int i=0;//同时存在全局变量和局部变量的情况下,优先使用局部变量
while(1)
{
//pthread_exit(arg);
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE,NULL);
printf("i=%d\n",i++);
sleep(1);
}
}
int main()
{
pthread_t tid;
pthread_create(&tid,NULL,func,NULL);
pthread_detach(tid);
int j=0;
while(1)
{
if(j==7)
pthread_cancel(tid);
printf("j=%d\n",j++);
sleep(1);
}
}
-------------------------------------------------------------------------------------------------------------------------------------
练习:线程回收和退出
#include <unistd.h>
#include <stdio.h>
#include <pthread.h>
static int abc;
void *thread_fun(void *p)
{
static int abc1;
while (1)
{
sleep(1);
printf("world %d\n", abc++);
if (abc > 4)
pthread_exit((void *)(&abc));
}
return NULL;
}
int main(int argc, char const *argv[])
{
static int abc2;
void *retval;
int fd;
int res;
pthread_t tid;
//创建一个线程
res = pthread_create(&tid, NULL, thread_fun, NULL);
if (res < 0)
{
perror ("thread create");
return -1;
}
pthread_join(tid, &retval);
printf("%d\n", *((int *)retval));
return 0;
}
------------------------------线程的同步与互斥------------------------------------
sudo apt-get install manpages-posix-dev 线程锁库安装
头文件:
#include <pthread.h>
初始化线程锁:
int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr);
参数一:线程锁的ID
参数二:线程锁的属性
上锁:
int pthread_mutex_lock(pthread_mutex_t *mutex); 上锁操作 -》“死等”上锁后他会一直等待解锁操作,直达进程死亡
参数一:线程锁ID
返回值:成功返回0 失败返回错误码
int pthread_mutex_trylock(pthread_mutex_t *mutex); 尝试上锁,他不会死等,只会立即返回上锁结果
解锁:
int pthread_mutex_unlock(pthread_mutex_t *mutex);
销毁锁:
int pthread_mutex_destroy(pthread_mutex_t *mutex);
-------------------------------------------------------------------------------------------------------------------------------------
练习:线程锁的使用
#include <stdio.h>
#include <pthread.h>
int i=0;//全局变量
pthread_mutex_t mutex; //所以线程都可用这把锁
pthread_mutex_t mutex1;
void *func(void *arg)
{
while(1)
{
//上锁
pthread_mutex_lock(&mutex1);
printf("ifunc=%d\n",i++);
//解锁
pthread_mutex_unlock(&mutex);
//sleep(1);
}
}
//使用线程锁达到同步的目的
int main()
{
//创建线程
pthread_t pid;
pthread_create(&pid,NULL,func,NULL);
//初始化线程锁 1
pthread_mutex_init(&mutex,NULL);
//初始化线程锁 2
pthread_mutex_init(&mutex1,NULL);
while(1)
{
//上锁
pthread_mutex_lock(&mutex);
printf("i=%d\n",i++);
//解锁
pthread_mutex_unlock(&mutex1);
// sleep(1);
}
}
-------------------------------------线程锁之条件变量----------------------------
初始化条件变量:
int pthread_cond_init(pthread_cond_t *restrict cond,const pthread_condattr_t *restrict attr);
参数一:条件变量ID
参数二:条件变量属性
返回值:返回0 ,失败返回错误号
//销毁条件变量
int pthread_cond_destroy(pthread_cond_t *cond);
参数一:要销毁的条件变量ID
返回值:返回0 ,失败返回错误号
等待条件到来:
int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex);
发送条件信号:
头文件:
#include <pthread.h>
函数原型
int pthread_cond_broadcast(pthread_cond_t *cond); ---》给所有条件变量发送信号
int pthread_cond_signal(pthread_cond_t *cond); ---》 发送一条条件信号
-------------------------------------------------------------------------------------------------------------------------------------
练习:条件变量的使用
#include <stdio.h>
#include <pthread.h>
int i=0;//全局变量
pthread_mutex_t mutex; //所以线程都可用这把锁
pthread_cond_t cond; //所有线程利用这个条件变量ID
void *func(void *arg)
{
while(1)
{
//上锁
printf("6666\n");
pthread_mutex_lock(&mutex);
//等待条件变量信号
printf("123456\n");
pthread_cond_wait(&cond,&mutex); //利用锁 把线程锁在该条件变量上
//接受到条件后他就不会阻塞
printf("ifunc=%d\n",i++);
//解锁
pthread_mutex_unlock(&mutex);
sleep(1);
}
}
//使用线程锁达到同步的目的
int main()
{
//创建线程
pthread_t pid;
pthread_create(&pid,NULL,func,NULL);
//初始化线程锁
pthread_mutex_init(&mutex,NULL);
//初始化条件变量
pthread_cond_init(&cond,NULL);
while(1)
{
//上锁
pthread_mutex_lock(&mutex);
printf("i=%d\n",i++);
if(i==5)
{
//发送条件信号
pthread_cond_signal(&cond);
}
//解锁
pthread_mutex_unlock(&mutex);
sleep(1);
}
}