当前位置: 首页 > news >正文

长宁区网站建设公工商营业执照网上查询官网

长宁区网站建设公,工商营业执照网上查询官网,电子商务网站建设品牌,网站开发与网页制作的区别传送门#xff1a;Linux多线程编程实例解析 . linux多线程编程——同步与互斥 . 传统多任务操作系统中一个可以独立调度的任务#xff08;或称之为顺序执行流#xff09;是一个进程。每个程序加载到内存后只可以唯一地对应创建一个顺序执行流#xff0c;即传统意义的进程。… 传送门Linux多线程编程实例解析 .  linux多线程编程——同步与互斥 . 传统多任务操作系统中一个可以独立调度的任务或称之为顺序执行流是一个进程。每个程序加载到内存后只可以唯一地对应创建一个顺序执行流即传统意义的进程。每个进程的全部系统资源是私有的如虚拟地址空间文件描述符和信号处理等等。使用多进程实现多任务应用时存在如下问题 1任务切换即进程间上下文切换系统开销比较大。虚拟地址空间以及task_struct 都需要切换 2多任务之间的协作比较麻烦涉及进程间通讯。因为不同的进程工作在不同的地址空间 所以为了提高系统的性能许多操作系统规范里引入了轻量级进程的概念也被称为线程。 一、线程基础 通常线程指的是共享相同地址空间的多个任务。线程最大的特点就是在同一个进程中创建的线程共享该进程的地址空间但一个线程仍用task_struct 来描述线程和进程都参与统一的调度。所以多线程的好处便体现出来 1大大提高了任务切换的效率因为各线程共享进程的地址空间任务切换时只要切换task_struct 即可 2线程间通信比较方便因为在同一块地址空间数据共享 当然共享地址空间也会成为线程的缺点因为共享地址空间如果其中一个线程出现错误比如段错误整个线程组都会崩掉 Linux之所以称呼其线程为LWP( Light Weight Process )因为从内核实现的角度来说它并没有为线程单独创建一个结构而是继承了很多进程的设计 1继承了进程的结构体定义task_struct 2没有专门定义线程ID复用了PID 3更没有为线程定义特别的调度算法而是沿用了原来对task_struct 的调度算法。 在最新的Linux内核里线程已经替代原来的进程称为调度的实际最小单位。 原来的进程概念可以看成是多个线程的容器称之为线程组即一个进程就是所有相关的线程构成的一个线程组。传统的进程等价于单线程进程。 每个线程组都有自己的标识符 tgid (数据类型为 pid_t )其值等于该进程(线程组)中的第一个线程(group_leader)的PID。 1、创建线程 pthread_create()函数描述如下 所需头文件#include pthread.h函数原型 int pthread_create(pthread_t *thread,const pthread_attr_t *attr,                                void *(* routine)(void *), void *arg) 函数参数 thread 创建的线程 attr 指定线程的属性NULL表示使用缺省属性 routine 线程执行的函数 arg 传递给线程执行的函数的参数 函数返回值 成功 0 出错 -1 1这里routine 是回调函数callback其函数类型由内核来决定这里我们将其地址传给内核这个函数并不是线程创建了就会执行而是只有当其被调度到cpu上时才会被执行具体回调函数的讲解移步Linux C 函数指针应用---回调函数 . 2arg 是线程执行函数的参数这里我们将其地址穿进去使用时需要先进行类型转换才能使用如果参数不止一个我们可以将其放入到结构体中 2、pthread_join () 函数 其函数描述如下 所需头文件#include pthread.h函数原型int thread_join(pthread_t thread, void  ** value_ptr)函数参数 thread 要等待的线程 value_ptr 指针 *value_ptr 指向线程返回的参数 函数返回值 成功 0 出错 -1 这里我们可以看到 value_ptr 是个二级指针其是出参存放的是线程返回参数的地址 3、pthread_exit 函数 其函数描述如下 所需头文件#include pthread.h函数原型int pthread_exit(void *value_ptr)函数参数value_ptr 线程退出时返回的值函数返回值 成功0 出错-1 和进程中的exit() 、wait()一样这里pthread_join 与 pthread_exit 是工作在两个线程之中 下面看一个实例 [cpp] view plaincopy #include stdio.h   #include stdlib.h   #include string.h   #include pthread.h      char message[32]  Hello World!;   void *thread_function(void *arg);      int main()   {       pthread_t a_thread;       void *thread_result;          if(pthread_create(a_thread,NULL,thread_function,(void *)message)  0)       {           perror(fail to pthread_create);           exit(-1);       }          printf(waiting for thread to finish\n);       if(pthread_join(a_thread,thread_result)  0)       {           perror(fail to pthread_join);           exit(-1);       }          printf(Message is now %s\n,message);       printf(thread_result is %s\n,(char *)thread_result);       return 0;   }      void *thread_function(void *arg)   {       printf(thread_function is running,argument is %s\n,(char *)arg);       strcpy(message,marked by thread);       pthread_exit(Thank you for the cpu time);   }   编译 [cpp] view plaincopy fsubuntu:~/qiang/thread/0107$ gcc -o thread thread.c -lpthread   fsubuntu:~/qiang/thread/0107$    线程通过第三方的线程库来实现所以这里要 -lpthread -l 是链接一个库这个库是pthread 执行结果如下 [cpp] view plaincopy fsubuntu:~/qiang/thread/0107$ ./thread    waiting for thread to finish   thread_function is running,argument is Hello World!   Message is now marked by thread   thread_result is Thank you for the cpu time   fsubuntu:~/qiang/thread/0107$    从这个程序我们可以看到线程之间是如何通信的线程之间通过二级指针来传送参数的地址这是进程所不具备的因为他们的地址空间独立但两个线程之间的通信传递的数据的生命周期必须是静态的。可以使全局变量、static修饰的数据、堆里面的数据这个程序中的message就是一个全局变量。其中一个线程可以修改它另一个线程得到它修改过后的message。 二、线程的同步和互斥 先来了解同步和互斥的基本概念 临界资源某些资源来说其在同一时间只能被一段机器指令序列所占用。这些一次只能被一段指令序列所占用的资源就是所谓的临界资源。 临界区对于临界资源的访问必须是互斥进行。也就是当临界资源被一个指令序列占用时另一个需要访问相同临界资源的指令序列就不能被执行。指令序列不能执行的实际意思就是其所在的进程/线程会被阻塞。所以我们定义程序内访问临界资源的代码序列被称为临界区。 互斥是指同事只允许一个访问者对临界资源进行访问具有唯一性和排它性。但互斥无法限制访问这个对资源的访问顺序即访问时无序的。 同步是指在互斥的基础上通过其他机制实现访问者对资源的有序访问。 1、线程间互斥 引入互斥(mutual   exlusion)锁的目的是用来保证共享数据的完整性。 互斥锁主要用来保护临界资源。每个临界资源都有一个互斥锁来保护任何时刻最多只能有一个线程能访问该资源线程必须先获得互斥锁才能访问临界资源访问完资源后释放该锁。如果无法获得锁线程会阻塞直到获得锁为止 通常我们在临界区前上锁临界区后解锁 1初始化互斥锁函数 所需头文件#include pthread.h函数原型 int pthread_mutex_init (pthread_mutex_t  *mutex,  pthread_mutexattr_t  *attr ) //初始化互斥锁 函数参数 mutex互斥锁 attr 互斥锁属性 // NULL表示缺省属性 函数返回值 成功0 出错-1 2申请互斥锁函数 所需头文件#include pthread.h函数原型 int pthread_mutex_lock(pthread_mutex_t *mutex) //申请互斥锁 函数参数 mutex互斥锁 函数返回值 成功0 出错-1 3释放互斥锁函数 所需头文件#include pthread.h函数原型 int pthread_mutex_unlock(pthread_mutex_t *mutex) //释放互斥锁 函数参数 mutex互斥锁 函数返回值 成功0 出错-1 下面是一个实例 [cpp] view plaincopy #include stdio.h   #include stdlib.h   #include string.h   #include pthread.h   #include unistd.h   //#define _LOCK_      unsigned int value1,value2,count;   pthread_mutex_t mutex;   void *function(void *arg);      int main()   {       pthread_t a_thread;          if(pthread_mutex_init(mutex,NULL)  0)       {           perror(fail to mutex_init);           exit(-1);       }          if(pthread_create(a_thread,NULL,function,NULL) ! 0)       {           perror(fail to pthread_create);           exit(-1);       }          while(1)       {           count;   #ifdef _LOCK_           pthread_mutex_lock(mutex);   #endif           value1  count;           value2  count;   #ifdef _LOCK_           pthread_mutex_unlock(mutex);   #endif       }       return 0;   }      void *function(void *arg)   {       while(1)       {   #ifdef _LOCK_           pthread_mutex_lock(mutex);   #endif           if(value1 ! value2)           {               printf(count  %d,value1  %d,value2  %d\n,count,value1,value2);               usleep(100000);           }   #ifdef _LOCK_           pthread_mutex_unlock(mutex);   #endif       }       return NULL;   }   执行结果如下 [cpp] view plaincopy fsubuntu:~/qiang/thread/0107$ ./mutex      count  3368408,value1  3368408,value2  3368407   count  44174760,value1  44174760,value2  44174759   count  69313865,value1  69313865,value2  69313864   count  139035309,value1  139035309,value2  139035308   count  168803956,value1  168803956,value2  168803955   count  192992611,value1  192992611,value2  192992610   count  224279903,value1  224279903,value2  224279902   count  259586793,value1  259586793,value2  259586792   count  282057307,value1  282057307,value2  282057306   count  321607823,value1  321607823,value2  321607822   count  351629940,value1  351629940,value2  351629939   count  374130545,value1  374130545,value2  374130544   count  400727525,value1  400727525,value2  400727524   count  440219988,value1  440219988,value2  440219987   count  466069865,value1  466069865,value2  466069864   count  500581241,value1  500581241,value2  500581240   count  522649671,value1  522649671,value2  522649670   count  569234325,value1  569234325,value2  569234324   count  608139152,value1  608139152,value2  608139151   count  639493957,value1  639493957,value2  639493956   .....   我们可以看到数据是不断被打印的说明 a 线程是可以访问临界资源的。 我们把#define  _LOCK_前面的注释去掉这时就加上了互斥锁执行结果如下 [cpp] view plaincopy fsubuntu:~/qiang/thread/0107$ ./mutex   此时并没有数据被打印说明此时a线程中 value1 与 value 2 一直是相等的说明主线程执行是a线程并无法访问临界资源的。 2、线程间同步 同步(synchronization) 指的是多个任务线程按照约定的顺序相互配合完成一件事情 线程间同步——P / V 操作 信号量代表某一类资源其值表示系统中该资源当前可用的数量。 信号量是一个受保护的变量只能通过三种操作来访问 1初始化 2P操作申请资源 3V操作释放资源PS含义如下 [cpp] view plaincopy if (信号量的值大于0)   {       请资源的任务继续运行       信号量的值 减一   }   else   {       请资源的任务阻塞   }   VS含义如下 [cpp] view plaincopy if (没有任务在等待该资源)   {       信号量的值 加一   }   else   {       唤醒第一个等待的任务让其继续运行   }   1、信号量初始化函数 所需头文件#include semaphore.h函数原型 int sem_int (sem_t *sem,int pshared,unsigned int value) //初始化信号量 函数参数 sem初始化的信号量 pshared信号量共享的范围0线程间使用 非0 进程间使用 value 信号量初值 函数返回值 成功0 出错-1 2P操作 所需头文件#include semaphore.h函数原型 int sem_wait (sem_t *sem) //P操作 函数参数 sem信号量 函数返回值 成功0 出错-1 3V操作 所需头文件#include semaphore.h函数原型 int sem_post(sem_t *sem) //V操作 函数参数 sem信号量 函数返回值 成功0 出错-1 下面是个实例 [cpp] view plaincopy #include stdio.h   #include stdlib.h   #include string.h   #include pthread.h   #include semaphore.h      char buf[60];   sem_t sem;   void *function(void *arg);      int main(int argc, char *argv[])   {       pthread_t a_thread;       void *thread_result;          if(sem_init(sem,0,0) ! 0)       {           perror(fail to sem_init);           exit(-1);       }          if(pthread_create(a_thread,NULL,function,NULL) ! 0)       {           perror(fail to pthread_create);           exit(-1);       }          printf(input quit to exit\n);       do         {           fgets(buf,60,stdin);           sem_post(sem);       }       while(strncmp(buf,quit,4) ! 0);              return 0;   }      void *function(void *arg)   {       while(1)       {           sem_wait(sem);           printf(you enter %d characters\n,strlen(buf) - 1);       }   }   执行结果如下 [cpp] view plaincopy fsubuntu:~/qiang/thread/0107$ ./sem    input quit to exit   xiao   you enter 4 characters   zhi   you enter 3 characters   qiang   you enter 5 characters   quit   fsubuntu:~/qiang/thread/0107$    我们可以看到两个线程是同步的。
http://www.zqtcl.cn/news/14432/

相关文章:

  • 全自动网站制作源码wordpress 渲染html
  • 东莞市建设小学网站北航刘禹导师做网站
  • 珠海教育局系统网站网站建设需求多少钱大概
  • 做模具的网站嵌入式软件开发工资高吗
  • 做网站怎么套模板做网站需要办什么证件
  • 网站开发用哪种语言android应用商店
  • 广西百色建设局网站酷家乐网站做墙裙教程
  • tk网站域名卖线面网站
  • it网站建设资讯网泰安网站优化
  • 个人域名 做公司网站做网站的怎么挣钱、
  • 一般企业网站建设合同大学生动漫主题网页制作
  • 有哪些做ae小动效的网站如何保存自己做的网站
  • 建站之星官网建设网络课程网站建设
  • 果汁网站模板WordPress主题改变登录页面
  • 电子商务网站上线活动策划学平面设计要多少钱
  • 网站怎么防采集乌兰察布建设局网站
  • 公司网站首页设计构想网站进入百度观察期
  • 网站开发与维护能做什么职业长沙招聘网站哪个最好
  • 手机网站建设渠道seo的中文含义是什么
  • 如何在线实现手机版网站建设我要发布信息
  • 网站死链怎么删除学校网站建设申请报告
  • 门户网站概念openwrt安装wordpress
  • 赤峰网站建设赤峰18互联网站做网站程序
  • wordpress是免费的吗网络seo是什么工作
  • 虚拟主机网站被挂马用旧电脑做服务器建网站用
  • 茶文化网站建设规划书范文长沙企业网站制作服务报价
  • 网站建设公司计划书重庆招聘信息
  • 用自己的电脑做主机建网站开发工具都有什么
  • 芜湖镜湖区做网站公司搜狗关键词排名此会zjkwlgs
  • 网站建设主要流程图中国最大的销售网站