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

做设计必须知道的几个网站吗产品设计排名

做设计必须知道的几个网站吗,产品设计排名,网站建设全过程及如何赚钱,黄骅贴吧房屋买卖✨个人主页#xff1a; 熬夜学编程的小林 #x1f497;系列专栏#xff1a; 【C语言详解】 【数据结构详解】【C详解】【Linux系统编程】 目录 1、线程创建 2、线程异常 3、线程用途 4、进程 VS 线程 5、线程控制 5.1、创建和等待线程 1、线程创建 线程能看到进程的大… ✨个人主页 熬夜学编程的小林 系列专栏 【C语言详解】 【数据结构详解】【C详解】【Linux系统编程】 目录 1、线程创建 2、线程异常 3、线程用途 4、进程 VS 线程 5、线程控制 5.1、创建和等待线程 1、线程创建 线程能看到进程的大部分资源下面做一个对全局变量修改的测试验证 代码演示  int gval 100;void* threadStart(void* args) {// 新线程while(true){std::cout new thread running... ,pid: getpid() ,gval: gval ,gval: gval std::endl;sleep(1);} }// 线程访问全局变量 int main() {pthread_t tid;pthread_create(tid,nullptr,threadStart,(void*)thread-new);// 主线程while(true){std::cout main thread running... ,pid: getpid() ,gval: gval ,gval: gval std::endl;gval; // 主线程修改全局变量sleep(1);}return 0; } 运行结果   2、线程异常 单个线程如果出现除零野指针问题导致线程崩溃进程也会随着崩溃线程是进程的执行分支线程出异常就类似进程出异常进而触发信号机制终止进程进程终止该进程内的所有线程也就随即退出 代码演示   // 单个线程崩溃会导致进程崩溃 int gval 100;void *threadStart(void *args) {// 新线程while (true){sleep(1);int x rand() % 5; // 生成0-4的随机数std::cout new thread running... ,pid: getpid() ,gval: gval ,gval: gval std::endl;// 随机数等于0则让线程崩溃if (x 0){int *p nullptr; // 空指针解引用问题*p 100;}} }// 线程访问全局变量 int main() {srand(time(nullptr));// 创建3个线程pthread_t tid1;pthread_create(tid1, nullptr, threadStart, (void *)thread-new1);pthread_t tid2;pthread_create(tid2, nullptr, threadStart, (void *)thread-new2);pthread_t tid3;pthread_create(tid3, nullptr, threadStart, (void *)thread-new3);// 主线程while (true){std::cout main thread running... ,pid: getpid() ,gval: gval ,gval: gval std::endl;gval; // 主线程修改全局变量sleep(1);}return 0; } 运行结果  3、线程用途 合理的使用多线程能提高CPU密集型程序的执行效率合理的使用多线程能提高IO密集型程序的用户体验如生活中我们一边写代码一边下载开发工具就是多线程运行的一种表现 4、进程 VS 线程 进程是资源分配的基本单位线程是调度的基本单位线程共享进程数据但也拥有自己的一部分数据: 线程ID一组寄存器(保存硬件上下文数据)栈(程序在运行的时候会形成各种临时变量临时变量被每个线程保存在自己的栈区)errno信号屏蔽字调度优先级 进程的多个线程共享 同一地址空间,因此Text Segment、Data Segment都是共享的,如果定义一个函数,在各线程中都可以调用,如果定义一个全局变量,在各线程中都可以访问到,除此之外,各线程还共享以下进程资源和环境: 文件描述符表每种信号的处理方式(SIG_ IGN、SIG_ DFL或者自定义的信号处理函数)当前工作目录用户id和组id 进程和线程的关系如下图: 如何看待之前学习的单进程 具有一个线程执行流的进程 。 线程调度成本为什么比进程更低(面试题) 一、进程与线程的基本概念 进程进程是资源分配的最小单位每个进程都有自己独立的地址空间系统需要为进程分配地址空间并建立数据表来维护其代码段、堆栈段和数据段。这种操作相对复杂且开销较大。线程线程是程序执行的最小单位资源调度的最小单位它是进程的一部分共享进程所拥有的资源。因此线程切换时无需像进程切换那样重新分配地址空间和维护数据表从而减少了开销。 二、上下文切换的开销 CPU上下文切换无论是进程调度还是线程调度都需要进行CPU上下文切换。这部分开销在两者中是相似的。CPU Cache/TLB命中率线程切换时由于多个线程共享进程的地址空间因此CPU Cache高速缓存和TLB转换后备缓冲器中的内容在切换后仍然有效命中率较高。而进程切换时由于地址空间的变化原有的Cache和TLB内容可能不再适用导致命中率下降触发更多的缺页中断从而增加了开销。 三、资源共享与通信 资源共享线程共享进程的资源包括地址空间、全局变量、静态变量等。这使得线程之间的通信更加便捷无需像进程间通信那样通过IPC进程间通信方式进行从而减少了通信开销。通信开销进程间通信需要借助额外的机制如管道、信号、共享内存等这些机制的实现和维护都会增加开销。而线程间通信则可以直接通过共享内存进行无需额外的通信机制。 四、创建与销毁的开销 创建开销由于进程需要分配独立的地址空间和维护数据表因此创建进程的开销相对较大。而线程则共享进程的地址空间无需进行这些操作因此创建线程的开销较小。销毁开销同样地由于进程拥有独立的资源因此在销毁时需要释放这些资源开销较大。而线程则无需释放独立的资源销毁开销相对较小。 5、线程控制 线程控制创建终止等待分离 POSIX线程库 与线程有关的函数构成了一个完整的系列绝大多数函数的名字都是以“pthread_”打头的要使用这些函数库要通过引入头文pthread.h链接这些线程函数库时要使用编译器命令的“-lpthread”选项 5.1、创建和等待线程 pthread_join() pthread_join - 等待指定的线程终止#include pthread.hint pthread_join(pthread_t thread, void **retval);参数 pthread_t thread这是你想要等待的线程的标识符。线程标识符是在创建线程时通过 pthread_create 函数返回的。void **retval这是一个指向指针的指针(二级指针)用于接收被等待线程的返回值。如果你不需要获取线程的返回值可以将这个参数设置为 nullptr。被等待线程的返回值应该是一个 void* 类型的指针在调用 pthread_exit 或从线程的启动函数返回时设置。 返回值 成功时pthread_join 返回 0。失败时返回一个错误码。常见的错误码包括 ESRCH指定的线程不存在。EINVAL线程不是可连接的即线程不是可加入的可能因为它已经终止了或者它是以分离状态创建的。EDEADLK检测到死锁在尝试加入一个已经由调用线程加入的线程时可能发生。其他可能的错误码具体取决于系统实现。 代码演示 新线程执行函数 void *threadRun(void *args) {int cnt 10;while(cnt){// 每隔一秒打印一次std::cout new thread run...,cnt: cnt-- std::endl;sleep(1);}return nullptr; } 主函数 int main() {pthread_t tid;// 创建新线程int n pthread_create(tid, nullptr, threadRun, (void *)thread 1);if (n ! 0) // 后面暂时不关心{std::cerr create thread errno std::endl;return 1;}std::cout main thread join begin... std::endl;// 等待新线程终止n pthread_join(tid,nullptr); if(n 0){std::cout main thread wait success std::endl;}return 0; } 运行结果  问题1 : main 和 new 线程谁先运行 不确定 问题2 : 我们期望谁最后退出 main thread最后退出类似与父进程最后退出回收子进程 , 你如何保证呢 join来保证。 不join呢 主线程活着新线程退出会造成类似僵尸问题 问题3 :tid是什么样子的是什么呢 tid通过10进制打印是一个很大的值tid实际上是一个虚拟地址可以通过16进制进行打印。 打印函数 // 10进制打印tid void PrintToDec(pthread_t tid) {std::cout tid: tid std::endl; }// 16进制打印tid std::string PrintToHex(pthread_t tid) {char buffer[128];snprintf(buffer,sizeof(buffer),0x%lx,tid);return buffer; } 主函数  int main() {pthread_t tid;// 创建新线程int n pthread_create(tid, nullptr, threadRun, (void *)thread 1);// 问题3 : tid是什么样子的是什么呢虚拟地址 为什么PrintToDec(tid); // 按照10进制方式打印std::string tid_str PrintToHex(tid); // 按照16进制方式打印std::cout tid: tid_str std::endl;std::cout main thread join begin... std::endl;// 等待新线程终止n pthread_join(tid,nullptr); if(n 0){std::cout main thread wait success std::endl;}return 0; } 运行结果  问题4 : 全面看待线程函数传参 我们可以传递任意类型但你一定要能想得起来也能传递类对象地址  方式一传字符串常量 代码演示  void *threadRun(void *args) {std::string name (const char*)args;int cnt 10;while(cnt){// 每隔一秒打印一次std::cout name run...,cnt: cnt-- std::endl;sleep(1);}return nullptr; } int main() {pthread_t tid;// 创建新线程int n pthread_create(tid, nullptr, threadRun, (void *)thread 1);std::string tid_str PrintToHex(tid); // 按照16进制方式打印出来std::cout tid: tid_str std::endl;std::cout main thread join begin... std::endl;// 等待新线程终止n pthread_join(tid,nullptr); if(n 0){std::cout main thread wait success std::endl;}return 0; } 运行结果  方式二传整数 代码演示  void *threadRun(void *args) {int a *(int*)args;// warning 系统为64位指针大小为8字节int为4字节int cnt 10;while(cnt){std::cout a run...,cnt: cnt-- std::endl;sleep(1);}return nullptr; }int main() {pthread_t tid;int a 100;int n pthread_create(tid, nullptr, threadRun, (void *)a);std::string tid_str PrintToHex(tid); // 按照16进制方式打印出来std::cout tid: tid_str std::endl;std::cout main thread join begin... std::endl;// 等待新线程终止n pthread_join(tid,nullptr); if(n 0){std::cout main thread wait success std::endl;}return 0; } 运行结果  方式二传类对象 代码演示  class ThreadData { public:std::string name;int num; }; void *threadRun(void *args) {ThreadData* td static_castThreadData*(args); // 安全类别强转 (ThreadData*)argsint cnt 10;while(cnt){std::cout td-name run...,num is td-num ,cnt: cnt-- std::endl; sleep(1);}return nullptr; }主函数 int main() {pthread_t tid;ThreadData td;td.name thread-1;td.num 1;int n pthread_create(tid, nullptr, threadRun, (void*)td); // 传递线程结构体对象std::string tid_str PrintToHex(tid); // 按照16进制方式打印出来std::cout tid: tid_str std::endl;std::cout main thread join begin... std::endl;// 等待新线程终止n pthread_join(tid,nullptr); if(n 0){std::cout main thread wait success std::endl;}return 0; } 运行结果   创建新线程访问栈上的空间不推荐因为当多个新线程访问同一个结构体数据时可能造成数据互相影响的问题如果只读问题不大但是如果一个线程对该数据进行修改那么后面所有线程访问的数据都会修改 // 再创建一个新线程使用同一个局部变量修改值两个都修改了 td.name thread-2; td.num 2; n pthread_create(tid, nullptr, threadRun, (void*)td); // 传递线程结构体对象 运行结果  推荐在堆上申请空间一个新线程申请一个类对象使用完毕释放空间  void *threadRun(void *args) {ThreadData* td static_castThreadData*(args); // 安全类别强转 (ThreadData*)argsint cnt 10;while(cnt){std::cout td-name run...,num is td-num ,cnt: cnt-- std::endl; sleep(1);}std::cout delete td: td std::endl;delete td; // 释放空间return nullptr; } int main() {pthread_t tid;ThreadData* td new ThreadData();td-name thread-1;td-num 1;int n pthread_create(tid, nullptr, threadRun, td); std::string tid_str PrintToHex(tid); // 按照16进制方式打印出来std::cout tid: tid_str std::endl;std::cout main thread join begin... std::endl;// 等待新线程终止n pthread_join(tid,nullptr); if(n 0){std::cout main thread wait success std::endl;}return 0; } 运行结果  问题5: 全面看待线程函数返回:  新线程函数返回值 1、只考虑正确的返回不考虑异常因为异常了整个进程就崩溃了包括主线程。 新线程通过函数返回值给主线程 代码演示   void *threadRun(void *args) {ThreadData* td static_castThreadData*(args); // 安全类别强转 (ThreadData*)argsint cnt 10;while(cnt){std::cout td-name run...,num is td-num ,cnt: cnt-- std::endl; // int* p nullptr;// *p 100; // 故意野指针sleep(1);}std::cout delete td: td std::endl;delete td; // 释放空间return (void*)111; } 主线程获取新线程的返回值信息  int main() {pthread_t tid;ThreadData* td new ThreadData();td-name thread-1;td-num 1;int n pthread_create(tid, nullptr, threadRun, td); std::cout main thread join begin... std::endl;// 等待新线程终止void* code nullptr; // 开辟了空间的n pthread_join(tid,code); if(n 0){// 主线程拿新线程的退出信息int会有精度损失Linux中地址8字节int4字节std::cout main thread wait success, new thread exit code: (uint64_t)code std::endl;}return 0; } 运行结果  新线程故意野指针 运行结果   2、我们可以传递任意类型但你一定要能想得起来也能传递类对象地址  类对象 class ThreadData { public:int Excute(){return x y;} public:std::string name;int x;int y; };class ThreadResult { public:std::string Print(){return std::to_string(x) std::to_string(y) std::to_string(result);} public:int x;int y;int result; }; 新线程函数 void *threadRun(void *args) {ThreadData* td static_castThreadData*(args); int cnt 10;ThreadResult* result new ThreadResult();while(cnt){sleep(3);std::cout td-name run...,cnt: cnt-- std::endl; result-result td-Excute();result-x td-x;result-y td-y;break;}std::cout delete td: td std::endl;delete td; // 释放空间return (void*)result; } 主函数 int main() {pthread_t tid;ThreadData* td new ThreadData();td-name thread-1;td-x 10;td-y 20;int n pthread_create(tid, nullptr, threadRun, td); std::cout main thread join begin... std::endl;// 等待新线程终止ThreadResult* result nullptr; // 开辟了空间的n pthread_join(tid,(void**)result); if(n 0){std::cout main thread wait success, new thread exit code: result-Print() std::endl;}return 0; } 运行结果  问题6 : 如何创建多线程呢  错误示范(X) 在for循环内部创建临时变量 代码演示   const int num 10;void *threadrun(void *args) {std::string name static_castconst char *(args);while (true){// 打印的线程名是乱的线程执行顺序是不确定的// 且因为在名字栈区for循环内部创建每切换一个线程名字就会被覆盖有问题std::cout name is running std::endl;sleep(1);}return nullptr; } int main() {// 问题6 : 如何创建多线程呢std::vectorpthread_t tids;for (int i 0; i num; i){// 1.有线程的idpthread_t tid;// 2.有线程的名字char name[128];snprintf(name, sizeof(name), thread-%d, i 1);pthread_create(tid, nullptr, threadrun, /*线程的名字*/ name);}// join todosleep(100);return 0; } 运行结果   正确示范 只需让name在堆区创建即可并修改格式化name函数 // 2.有线程的名字(正确示范) char* name new char[128]; snprintf(name, 128, thread-%d, i 1); 等待(终止)多线程 创建好新线程之后保存每个线程的tid遍历vector终止新线程即可 代码演示   const int num 10;void *threadrun(void *args) {std::string name static_castconst char *(args);while (true){// 打印的线程名是乱的线程执行顺序是不确定的// 且因为在名字栈区for循环内部创建每切换一个线程名字就会被覆盖有问题std::cout name is running std::endl;sleep(1);break;}// return nullptr;return args; } int main() {// 问题6 : 如何创建多线程呢std::vectorpthread_t tids;for (int i 0; i num; i){// 1.有线程的idpthread_t tid;// 2.有线程的名字(错误示范)// char name[128];// snprintf(name, sizeof(name), thread-%d, i 1);// 2.有线程的名字(正确示范)char* name new char[128];snprintf(name, 128, thread-%d, i 1);pthread_create(tid, nullptr, threadrun, /*线程的名字*/ name);// 3.保存所有线程的id信息tids.emplace_back(tid);}// join todofor(auto tid : tids){void* name nullptr;pthread_join(tid,name);// std::cout PrintToHex(tid) quit std::endl;std::cout (const char*)name quit std::endl;delete (const char*)name;}// sleep(100);return 0; } tid方式打印 运行结果   线程名方式打印 运行结果
http://www.pierceye.com/news/776660/

相关文章:

  • 如何做网站卖东西长春互联网公司排名
  • 怎样拥有自己的网站制作网站的步骤和方法
  • 北京电子商务app网站建设大兴小程序源码如何部署到服务器
  • 设计找图网站网站用什么构建
  • 做微信的网站叫什么软件湛江网站建设制作维护
  • 做网站商城多少钱wordpress链接公众号
  • 数码产品销售网站建设策划书金融类网站模板
  • 档案网站建设视频网络软营销的案例
  • 德州市建设局质监站网站织梦做的网站打包在dw修改
  • 做那个男女的视频网站湖南响应式网站公司
  • 1个ip可以做几个网站电商网站建设阿里云
  • 网站做seo需要些什么wordpress虎嗅破解版
  • 网站开发按钮图片素材巩义自助建站优化
  • 石家庄网站建设接单常见的网络直接营销有哪些
  • 上海网站建设技术托管找合伙人做网站
  • 网站和自媒体都可以做东莞专业营销网站建设推广
  • 毕业设计网站怎么做校园网二手书交易网站建设
  • 网站运营托管协议凡科建设网站还用买服务器吗
  • 黑龙江省建设网官方网站erp系统软件免费版
  • 网站建设案例算命网站百度搜索站长平台网站
  • 手机wap网站模板 带后台thefox wordpress
  • 公司网站建设与设计制作游戏网站的设计方案
  • 移动端网站设计规范程序员帮忙做放贷网站
  • 网站到期查询广西建设信息网
  • 服务器可以放几个网站市场调研的五个步骤
  • 网站前置审批h5页面制作软件thinkphp
  • 企业网站设计调查问卷步骤记录器
  • dw里响应式网站怎么做郑州电力高等专科学校学费多少
  • 用app怎么样建网站深圳专业做网站的
  • 怎样做浏览的网站不被发现互联网营销师报考条件