1,线程与进程的区别
(1)进程
是一个正在执行的程序,是系统资源分配的实体
每个进程都有自己的PCB
(2)线程
进程和线程创建 内核使用的都是clone函数;
所有的缺省的线程平分栈的大小
线程栈与线程栈之间有一款线程安全区。
进程是资源竞争的基本单位
线程是程序执行的最小单位
线程共享进程数据,代码段,堆,但是有自己拥有的东西:线程ID>一组寄存器>栈>errno>信号屏蔽字>调度优先级
线程中最好不要处理信号;
操作系统引入线程的目的:
进程在运行时,由于进程调度算法的原因,不可避免的会出现进程之间的切换,而进程之间的切换时非常耗时的,为了解决这一问题,引入了多线程的解决方法;
线程,又称轻进程,在一个进程中创建多个线程去处理多个问题,线程在切换时不会切换进程,从而节省了时间。
不同进程的线程之间切换会引起进程的切换,同一进程中的线程切换不会引起进程的切换。进程的切换一定会引起线程的切换。
2,线程操作
(1)线程的创建
int pthread_create(pthread_t thread, const pthread_attr_t *attr, void (start_routine) (void ), void *arg);
pthread_create(线程ID,线程属性,线程需要执行的函数的地址,传给线程启动函数的参数)
(2)等待线程
int pthread_join(pthread_t thread,void **arg);
(3)结束线程
1,return
2,pthread_exit;(只会退出一个线程,不能退出进程,进程中的其他线程依然在执行,最后一个线程例外)
3,pthread_cancel;(关闭一个其他的线程)//遇到一个cancel点才会结束到一个线程
pthread_testcancel();(设置cancel点)
(4)获取线程id
pthread_t pthread_self();
(5)线程分离
int pthread_detach(pthread_t tid);
(6)初始化线程
int pthread_attr_init(pthread_attr_t* attr);
int ptnread_attr_destory(pthread_attr_t* attr);
Detach state = PTHREAD_CREATE_JOINABLE //线程分离属性
Scope = PTHREAD_SCOPE_SYSTEM
Inherit scheduler = PTHREAD_INHERIT_SCHED
Scheduling policy = SCHED_OTHER
Scheduling priority = 0
Guard size = 4096 bytes //线程之间的安全距离
Stack address = 0x40196000 //线程栈初始地址
Stack size = 0x201000 bytes //线程栈大小
(1)自己定义线程栈
int pthread_attr_setstack(pthread_attr_ t* attr, void* attraddr,size_t stacksize);
(2)设置线程栈的大小
int pthread_attr_setstacksize(pthread_attr_t * attr,size_t stacksize);
下面创建一个线程实例来加深理解
#include <stdio.h> #include <stdlib.h>
#include <pthread.h>
#include <string.h>
void *route1()
{
while(1)
printf("hello\n");
}
void *route2()
{
while(1)
printf("hello router2\n");
}
void *route3()
{
while(1)
printf("hello route3\n");
}
int main() {
pthread_t tid1;
pthread_t tid2;
pthread_t tid3;
int ret1 = pthread_create(&tid1,NULL,route1,NULL);
if(ret1!=0)
printf("pthread_create:%s\n",strerror(ret1));
int ret2 = pthread_create(&tid2,NULL,route2,NULL);
if(ret2!=0)
printf("ptreath_create2:%s\n",strerror(ret2));
int ret3 = pthread_create(&tid3,NULL,route3,NULL);
if(ret3!=0)
printf("pthread_create3:%s\n",strerror(ret3));
//1当进程退出,进程中所有线程就退出
//解决办法:pthread_join等待线程
//2创建好线程以后,每个线程都从参与时间片的分配
//3当线程处理函数结束之后,线程就结束
// pthread_join(tid,NULL);
while(1)
printf("hello.man\n");
}
线程的同步与互斥
1,线程分离
pthread_detach(pthread_t thread);
//互斥锁:同步线程对共享数据的访问
建议锁,不是强制的
1,定义全局变量 pthread_mutex_t metux;
2,初始化 pthread_mutex_init(&metux,NULL);
3, 上锁:pthread_mutex_lock(&mutex); mutex ==1 将mutex置0?返回
mutex==0? 等待
4,解锁:pthread_mutex_unlock(&mutex); mutex=1,返回
5,销毁:pthread_mutex_destory(&mutex);
void pthread_cleanup_push(void(*routine)(void*),void *arg); 回调函数遇到//1pthread_exit() 才会触发
//2,pthread_cancel()
//3,pop(1)
void pthread_cleanup_pop(int execute);
//自旋锁
1,pthread_spin_t spin
2,pthrad_t_spin_init
3,pthrad_t_spin_lock
4,pthrad_t_spin_unlock
5,pthrad_t_spin_destory
//读写锁:读读共享,读写互斥,写的优先级高
1,pthread_rwlock_t rwlock;
2,pthread_rwlock_init(&rwlock,NULL)
3,pthread_rwlock_rdlock(&rwlock);
4,pthread_rwlock_wrlock(&rwlock);
5,pthread_rwlock_unlock(&rwlock);
6,pthread_rwlock_destory(&rwlock);
//条件变量 同步共享数据的值
1,pthread_cond_t cond
2,pthread_cond_init(&cond,NULL)
3,pthread_cond_wait(&cond,&mutex) //阻塞,将mutex置为1
//返回,将mutex恢复为原样
4,pthread_cond_signal(&cond)
5,pthread_cond_destory(&cond)
使用规范:
pthread_mutex_lock(&mutex);
while(条件不满足)
pthread_cond_wait(&cond,&mutex)
pthread_mutex_unlock(&mutex);
pthread_mutex_lock(&mutex);
pthread_cond_signal(&cond); //如果没有线程等在wait,singal就丢失
pthread_mutex_unlock(&mutex);
POSIX信号量:
初始化信号量
int sem_init(sem_t*sem,
int pshare,//表示本进程内多个线程的同步互斥
unsigned int value);//设置初值
销毁信号量
int sem_destory(sem_t* sem);
p操作
int sem_wait(sem_t* sem);
v操作
int sem_post(sem_t* sem);