使用门户网站网络推广方法,好搜网站提交入口,企业新网站seo推广,网站建设书 模板下载概述 
进程与线程 进程 : 系统分配资源的基本单位 , 可以简单理解为一个正在进行的程序  线程 : 操作系统调度的最小单位 , 就是一段代码的执行顺序 注意#xff1a; 1, 一个进程必须要有一个线程 , 该线程被称为主线程  2, 一个进程可以有多个线程 , 除主线程外的其他线程都是…概述 
进程与线程 进程 : 系统分配资源的基本单位 , 可以简单理解为一个正在进行的程序  线程 : 操作系统调度的最小单位 , 就是一段代码的执行顺序 注意 1, 一个进程必须要有一个线程 , 该线程被称为主线程    2, 一个进程可以有多个线程 , 除主线程外的其他线程都是子线程    3, 进程被销毁时 , 其中的线程也将被销毁 .    4, 线程是轻量级的进程 LWP  light weight process 在  Linux  环境下线程的本    质仍是进程。    5, 进程所有线程都共享该进程的资源。   线程的特点 类  Unix  系统中早期是没有 “ 线程 ” 概念的 80  年代才引入借助进程机制实现出了线程的概念。  因此在这类系统中进程和线程关系密切  1)  线程是轻量级进程 (light-weightprocess) 也有  PCB 创建线程使用的底层函数和进程一样都是 clone  2)  从内核里看进程和线程是一样的都有各自不同的  PCB.  3)  进程可以蜕变成线程  4)  在 linux  下线程最是小的执行单位进程是最小的分配资源单位  实际上无论是创建进程的  fork 还是创建线程的  pthreadcreate 底层实现都是调用同一个内核函数 clone  。  Ø 如果复制对方的地址空间那么就产出一个 “ 进程 ”   Ø 如果共享对方的地址空间就产生一个 “ 线程 ” 。  Linux 内核是不区分进程和线程的 , 只在用户层面上进行区分。所以线程所有操作函数pthread* 是库函数而非系统调用  线程共享与非共享的资源 共享的  1)  文件描述符表    2)  每种信号的处理方式    3)  当前工作目录    4)  用户 ID 和组 ID    5)  内存地址空间  (.text/.data/.bss/heap/ 共享库 )    非共享的    1)  线程  id    2)  处理器现场和栈指针 ( 内核栈 )    3)  独立的栈空间 ( 用户空间栈 )    4) errno  变量    5)  信号屏蔽字    6)  调度优先级    现成的优缺点 优点 提高程序并发性    开销小    数据通信、共享数据方便    缺点    库函数不稳定    调试、编写困难、 gdb  不支持    对信号支持不好 优点相对突出缺点均不是硬伤。 Linux  下由于实现方法导致进程、线程差别不是很大。     查看的指定的线程号LWP) 
ps - Lf  pid 
pid : 进程号 
注意 由于线程库原本不是系统本身的 , 所以在链接时需要手动链接库文件 编译源文件时输入gcc *.c -l pthread 线程相关函数 获取当前线程号 
简述  线程号只在它所属的进程环境中有效。  线程号则用  pthread_t  数据类型来表示 Linux  使用无符号长整数表示。 函数 所需头文件            #include pthread.h    函数            pthread_t pthread_self(void);    功能            获取线程号。    参数            无    返回值            调用线程的线程 ID  。    示例   #include stdio.h
#include unistd.h
#include pthread.h
int main()
{pthread_t pthid  pthread_self();printf(pthid%ld\n,pthid);return 0;
}  创建线程 
函数 所需头文件  #include pthread.h  函数  int pthread_create(pthread_t *thread, const pthread_attr_t *attr,  void *(*start_routine)(void *), void *arg );  参数  thread线程标识符地址。  attr线程属性结构体地址通常设置为  NULL 。  start_routine线程函数的入口地址。  arg传给线程函数的参数。  返回值  成功0  失败非 0 示例 #include stdio.h
#include pthread.h
// 注意线程调用的函数返回值为任意指针类型
void *myfunc01()
{printf(线程%ld正在执行\n, pthread_self());return NULL;
}
void *myfunc02(void *arg)
{printf(线程%ld正在执行,参数为:%s\n, pthread_self(), (char *)arg);return NULL;
}
int main(int argc, char const *argv[])
{pthread_t p1, p2, p3;pthread_create(p1, NULL, myfunc01, NULL);pthread_create(p2, NULL, myfunc02, Thread2);pthread_create(p3, NULL, myfunc02, Thread3);getchar();return 0;
} 线程的回收 作用  等待线程结束此函数会阻塞并回收线程资源类似进程的  wait()  函数。如果线程已经结束那么该函数会立即返回。     函数             #include pthread.h            int pthread_join(pthread_t thread, void **retval);    参数            thread被等待的线程号。            retval用来存储线程退出状态的指针的地址 , 即回收的线程调用的函数的返回值    返回值            成功0            失败非 0    示例   #include stdio.h
#include pthread.h
#include unistd.h
void *myfunc01(void *argv)
{int *time  (int *)argv;printf(线程A%ld将于%d秒后销毁\n, pthread_self(), *time);sleep(*time);return 线程A;
}
void *myfunc02(void *argv)
{int *time  (int *)argv;printf(线程B%ld将于%d秒后销毁\n, pthread_self(), *time);sleep(*time);return 线程B;
}
int main(int argc, char const *argv[])
{int n01  3, n02  5;pthread_t p1, p2;pthread_create(p1, NULL, myfunc01, n01);pthread_create(p2, NULL, myfunc02, n02);void *argv01, *argv02;pthread_join(p1, argv01);pthread_join(p2, argv02);printf(%s被回收\n, (char *)argv01);printf(%s被回收\n, (char *)argv02);return 0;
}    线程的分离 作用  使调用线程与当前进程分离分离后不代表此线程不依赖与当前进程线程分离的目的    是将线程资源的回收工作交由系统自动来完成也就是说当被分离的线程结束之后系    统会自动回收它的资源。所以此函数不会阻塞。   函数  头文件  #include pthread.h  函数  void pthread_detach(patread_t thread);  参数  thread线程号  示例  #include stdio.h
#include pthread.h
#include unistd.h
void *fun1(void *arg)
{printf(线程1开始执行\n);sleep(3);return NULL;
}
void *fun2(void *arg)
{printf(线程2开始执行\n);sleep(1);return NULL;
}
int main(int argc, char const *argv[])
{pthread_t tid1;pthread_t tid2;pthread_create(tid1,NULL,fun1,NULL);pthread_create(tid2,NULL,fun2,NULL);pthread_detach(tid1);pthread_detach(tid2);getchar();return 0;
}   案例1多线程遍历字符串 
#include stdio.h
#include pthread.h
#include unistd.h
#include string.h
void *fun(void *arg)
{printf(len  %ld\n,strlen(arg));char *txt  (char *)arg;char buf[32]  {0};strcpy(buf,txt);printf(线程%ld开始执行\n,pthread_self);for(int i  0;i  strlen(buf);i){printf(%c\n,buf[i]);sleep(1);}printf(线程%ld执行结束\n);
}
int main(int argc, char const *argv[])
{char buf[32]  {0};while(1){// memset(buf,0,32);printf(请输入要打印的字符\n);fgets(buf,32,stdin);buf[strlen(buf)-1]  0;if(strcmp(buf,886)0){break;}    pthread_t t;pthread_create(t,NULL,fun,buf);}return 0;
} 
线程的退出 作用 退出当前线程。一个进程中的多个线程是共享该进程的数据段因此通常线程退出后    所占用的资源并不会释放。     函数    所需头文件            #include pthread.h    函数            void pthread_exit(void *retval);    参数            retval存储线程退出状态的指针。    返回值            无    示例    #include stdio.h
#include pthread.h
#include unistd.h
void *fun(void *arg)
{for(int i  0;i  10;i){printf(%d\n,i);sleep(1);if(i  3){pthread_exit(NULL);}}return NULL;
}
int main(int argc, char const *argv[])
{pthread_t tid;pthread_create(tid,NULL,fun,NULL);pthread_detach(tid);return 0;
}线程的取消 作用  退出指定线程    注意 :    线程的取消并不是实时的而有一定的延时。需要等待线程到达某个取消点 ( 检查点)    检测点类似与游戏的存档不是实时的需要到特定的地方才会存档    函数           #include pthread.h            int pthread_cancel(pthread_t thread);  参数  thread 目标线程id  返回值  成功0  失败出错编号  示例   #include stdio.h
#include pthread.h
#include unistd.h
void *fun(void *arg)
{for(int i  0;i  10;i){printf(%d\n,i);sleep(1);}return NULL;
}
int main(int argc, char const *argv[])
{pthread_t tid;pthread_create(tid,NULL,fun,NULL);sleep(3);pthread_detach(tid);pthread_join(tid,NULL);return 0;
}线程的属性了解 
概述 Linux  下线程的属性是可以根据实际项目需要进行设置之前我们讨论的线程都是采  用线程的默认属性默认属性已经可以解决绝大多数开发时遇到的问题。  如我们对程序的性能提出更高的要求那么需要设置线程属性比如可以通过设置线程栈  的大小来降低内存的使用增加最大线程个数。  线程树形结构体 typedef struct  {  int  etachstate ;  // 线程的分离状态  int  schedpolicy ;  // 线程调度策略  struct  sched_param schedparam ;  // 线程的调度参数  int  inheritsched ;  // 线程的继承性  int  scope ;  // 线程的作用域  size_t  guardsize ;  // 线程栈末尾的警戒缓冲区大小  int  stackaddr_set ;  // 线程的栈设置  void * stackaddr ;  // 线程栈最低地址 , 即线程栈的地址 , 默认是从所  属的进程的栈空间划分  size_t  stacksize ;  // 线程栈的大小  }  pthread_attr_t ; 注意 1.  线程分离状态    2.  线程栈大小默认平均分配    3.  线程栈警戒缓冲区大小位于栈末尾    4.  线程栈最低地址    以上属性的属性值不能直接设置须使用相关函数进行操作初始化的函数为    pthread_attr_init 这个函数必须在 pthread_create  函数之前调用。之后须用    pthread_attr_destroy  函数来释放资源。  线程属性相关函数 
初始化 作用 :  初始化线程属性     函数             int pthread_attr_init(pthread_attr_t *attr);    返回值            成功0             失败错误号    销毁 作用 销毁线程属性     函数   int pthread_attr_destroy(pthread_t *attr);  返回值  成功0  失败错误号   分离状态 作用 : 设置分离状态  函数   int pthread_attr_setdetachstate(pthread_attr_t *attr,int detachstate);  参数  attr:已初始化的线程属性  detachstate:  分离状态 PTHREAD_CREATE_DETACHED 分离线程           PTHREAD_CREATE_JOINABLE 非分离线程     作用 : 获取分离状态    int pthread_attr_getdetachstate(pthread_attr_t *attr, int    *detachstat);    参数 :            attr已初始化的线程属性            detachstate    分离状态 PTHREAD_CREATE_DETACHED 分离线程    PTHREAD_CREATE_JOINABLE 非分离线程   示例   #include stdio.h
#include pthread.h
#include unistd.h
void *fun(void *arg)
{int i  0;while(1){printf(%lu正在运行i%d\n,pthread_self(),i);sleep(1);}
}
int main(int argc, char const *argv[])
{pthread_attr_t attr;pthread_attr_init (attr);pthread_attr_setdetachstate(attr,PTHREAD_CREATE_DETACHED);//设置分离属性pthread_t tid;pthread_create(tid,NULL,fun,NULL);printf(5秒后将结束线程\n);sleep(5);pthread_cancel(tid);sleep(1);printf(销毁线程\n);pthread_attr_destroy(attr);return 0;
}线程栈相关 
概述 // 设置栈的地址  int pthread_attr_setstack(pthreadattrt *attr, void *stackaddr, sizet stacksize);  参数  attr指向一个线程属性的指针  stackaddr设置的栈的地址  stacksize设置的栈的大小  返回值         成功0 失败错误号  // 得到栈的地址  int pthread_attr_getstack(pthreadattrt *attr, void **stackaddr, sizet*stacksize);  参数  attr指向一个线程属性的指针  stackaddr返回获取的栈地址  stacksize返回获取的栈大小  成功 0 失败错误号  // 设置线程所使用的栈空间大小  int pthread_attr_setstacksize(pthreadattrt *attr, sizet stacksize);  参数  attr指向一个线程属性的指针  stacksize设置的栈大小  成功 0 失败错误号  // 得到线程所使用的栈空间大小  int pthread_attr_getstacksize(pthreadattrt*attr, sizet *stacksize);  参数  attr指向一个线程属性的指针  stacksize获取线程的栈大小  成功 0 失败错误号 示例 #include stdio.h
#include pthread.h
#include unistd.h
#include 
void *fun(void *arg)
{int i  0;while(1){printf(%lu线程正在执行i%d\n,pthread_self(),i);sleep(1);}return NULL;
}
int main(int argc, char const *argv[])
{pthread_attr_t attr;pthread_attr_init(attr);pthread_attr_setdetachstate(attr,PTHREAD_CREATE_DETACHED);void *stackaddr  calloc(1,128);if(stackaddr  NULL){perror(null);return 0;}pthread_attr_setstack(attr,stackaddr,128);pthread_t tid;printf(线程在5秒后结束\n);pthread_create(tid,attr,fun,NULL);sleep(5);pthread_cancel(tid);sleep(1);pthread_attr_destroy(attr);free(stackaddr);return 0;
}注意事项 1)  主线程退出其他线程不退出主线程应调用  pthread_exit  2)  避免僵尸线程  a) pthread_join  b) pthread_detach  c) pthread_create 指定分离属性  被  join  的线程可能在  join  函数返回前就释放完自己的所有内存资源所以不应当返回被回收线程栈中的值; 3) malloc  和  mmap  申请的内存可以被其他线程释放  4)  应避免在多线程模型中调用  fork 除非马上  exec 子进程中只有调用  fork  的线程存在其他线程 t  在子进程中均  pthread_exit  5)信号的复杂语义很难和多线程共存应避免在多线程引入信号机制 案例 火车票售票问题  定义一个记录火车票的剩余数量  4 个窗口同时销售该火车票  代码 #include stdio.h
#include pthread.h
#include unistd.h
#include string.h
int ticket  100;
void *sale(void *name)
{char buf[32]  {0};strcpy(buf,(char*) name);while(ticket  0){ticket--;sleep(0.5);printf(%s售卖了一张船票,还剩%d张船票\n,buf,ticket);}
}
int main(int argc, char const *argv[])
{pthread_t tid1,tid2,tid3,tid4;pthread_create(tid1,NULL,sale,一号窗口);pthread_create(tid2,NULL,sale,二号窗口);pthread_create(tid3,NULL,sale,三号窗口);pthread_create(tid3,NULL,sale,四号窗口);pthread_detach(tid1);pthread_detach(tid2);pthread_detach(tid3);pthread_detach(tid4);getchar();return 0;
} 作业 1, 整理笔记  2, 完成以下情况  一个线程打印1~52  一个线程打印a~z  3, 使用代码模拟龟兔赛跑  乌龟每秒1 米  兔子每秒5 米  赛程100 米  兔子在临近终点睡觉了, 导致乌龟赢了  4, 完成售票案例 , 查看并分析结果 , 说明原因 代码参考上面案例 原因 是因为卖了第一张票后其他三个窗口在抢cpu执行权在第一张票卖出去提示的信息还未执行的时候其他三个线程有一个线程有一个将cpu执行权抢了过去这是票数实际是99同理以此类推其他线程将cpu执行权抢了过去所以将卖了四张票后才第一次打印提示信息这时实际票数已经是96张所以这时提示的信息中将之前的四次卖票纪律一次性打出来了所以都是剩余96张。总之这是个异步在栈中每个线程都将有各自独立的ticket都是100张。 解决办法 是要解决其中异步的问题所以要解决这一问题就是要实现同步让四个线程只对一个ticket操作就可以。 简单的可以用将ticket设置为全局变量