免费手机网站建站平台自建网站
web/
2025/9/29 23:44:58/
文章来源:
免费手机网站建站平台,自建网站,今天郑州新闻头条,dede页码的调用 网站进程与线程
进程#xff1a;直观的说就是任务管理器中各种正在运行的程序。对于操作系统来说#xff0c;进程仅仅是一个数据结构#xff0c;并不会真实的执行代码
线程#xff1a;通常被称作但并不真的是轻量级进程或实际工作中的进程#xff0c;它会真实的执行代码。每…进程与线程
进程直观的说就是任务管理器中各种正在运行的程序。对于操作系统来说进程仅仅是一个数据结构并不会真实的执行代码
线程通常被称作但并不真的是轻量级进程或实际工作中的进程它会真实的执行代码。每个线程都有一个需要执行的代码块称为线程回调函数。每个进程启动的时候会同步启动一个主线程而主线程所执行的代码块就是main函数。当main函数结束时主线程结束并销毁同时其他子线程随之销毁
真并发与伪并发
伪并发
在早期的cpu即单核cpu中因性能核心各方面较为落后并发编程实际是一个伪并发编程即系统中所有进程按照优先级去抢占cpu时间片也就是系统一会执行这个一会执行哪个。
由于抢占时间片所需时间较短所以我们并不觉得程序卡顿。但各进程抢占cup时间片是一个很麻烦的事情cpu虽然提供任务切换的功能即TSS任务段但Windows并不使用。这是因为Windows自己实现了线程调度即在线程切换时上个线程代码执行到的地方的线程的状态线程上下文通用寄存器段寄存器硬件调试寄存器EIP指令指针寄存器EFLAGS等都会被Windows通过WindowsContext保存直到再次切换回来后再加载
真并发
随着科技的发展cpu由单核cpu变成了多核cpu。此时多个核心可以同时独立执行一个 任务此时也称作真并发
并发形式
1.多进程并发一个进程里只有一个线程同时启动多个进程实现并发,如浏览器打开的多个窗口
2.多线程并发一个进程内运行多个线程是真实的并发。其中存在变量的访问问题具体如下有Value 100 全局变量以及AB两个线程。初始时A,B线程访问Value访问值都是100现AB两线程都对Value进行。但操作完成后Value的值为101丢失了一个操作。这种情况叫做线程同步问题
线程的生存周期
1.当该线程回调函数执行完毕时自然死亡
2.当主线程死亡时子线程被动死亡
并发与并行并发更强调数量并行更强调性能
线程应用
普通函数应用
#includeiostream
#includethread
void FirstThreadCallBack() //构建一个普通函数作为子线程
{for (size_t i 0; i 100000; i){std::cout First: i std::endl;}
}
int main()
{std::thread obj(FirstThreadCallBack); //声明线程对象启动一个线程去执行线程回调函数for (size_t i 0; i 100000; i){std::cout main: i std::endl;}system(“pause”);//加上此函数使主线程不会结束让我们更清晰看到线程并发的过程。否则主线程结束子线程随之结束return 0;
}此时程序会同时进行上述两个循环打印
仿函数应用
#includeiostream
#includethread
class Exec//一个仿函数
{
public:void operator()()const{std::cout Exec std::endl;}
};
int main()
{Exec e;std::thread obj(e);return 0;
}此时打印Exec
Lambda应用
#includeiostream
#includethread
int main()
{std::thread obj([] {std::cout Lambda std::endl; });return 0;
}此时程打印Lambda
综上可知任何可以调用的类型都可以用于线程对象的构造函数传参
线程死亡
一旦线程启动了我们就需要知道线程是怎么结束的
1.自然死亡:thread析构函数terminate()在子线程执行完毕后析构子线程
2.非自然死亡thread析构函数执行完毕时子线程析构但子线程并没有执行完毕
3.等待绝对的自然死亡 等待子线程执行完毕后程序再进行执行
4.不再等待主线程存活时后台运行依赖于主线程的存活
5.如果一个线程是Windows原生线程主线程销毁后其也会死亡
Windows原生线程
现在我们验证一下当主线程死亡时Windows原生线程会不会死亡
#includeiostream
#includethread
#includewindows.h
DWORD ThreadCallBack(LPVOID lpThreadParameter)
{for (size_t i 0; i 100000; i){std::cout First: i std::endl;}return 0;
}
int main()
{CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)ThreadCallBack, NULL, NULL, NULL);//创建了一个windows原生线程return 0
}
此时运行程序发现随着主线程的结束该Windows原生线程死亡
等待死亡
#includeiostream
#includethread
#includewindows.h
DWORD ThreadCallBack(LPVOID lpThreadParameter)
{for (size_t i 0; i 100000; i){std::cout First: i std::endl;}return 0;
}
int main()
{HANDLE hThread CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)ThreadCallBack, NULL, NULL, NULL);//创建一个原生的Windows线程WaitForSingleObject(hThread, -1); //此时主线程会永久等待该子线程结束以后再结束return 0
}此时运行程序原生线程不会死亡直到它运行完毕
阻塞等待
#includeiostream
#includethread
#includewindows.h
DWORD ThreadCallBack(LPVOID lpThreadParameter)
{for (size_t i 0; i 100000; i){std::cout First: i std::endl;}return 0;
}
int main()
{std::thread obj(FirstThreadCallBack);//创建一个普通的线程obj.join(); //阻塞等待作用是在此处等待子线程结束程序再继续运行。//当使用此函数时我们通常需要加一个异常处理。这是因为子线程可能会出现一个异常报错而导致无法执行完毕以至于程序一直处于阻塞等待的情况return 0
}此时运行程序知道子线程运行完毕主线程才会结束
不再等待
#includeiostream
#includethread
#includewindows.h
DWORD ThreadCallBack(LPVOID lpThreadParameter)
{for (size_t i 0; i 100000; i){std::cout First: i std::endl;}return 0;
}
int main()
{std::thread obj(FirstThreadCallBack);obj.detach(); //不再等待同Windows原生线程一样主线程死亡其子线程也死亡
//此时额外加一个循环程序在执行该循环时主线程没有死亡子线程也不会死亡而是一起执行两个线程for (size_t i 0; i 100000; i) {std::cout main: i std::endl;}return 0;
}
线程同步问题
问题演示
如下当我们演示一个简单的线程同步
#includeiostream
#includethread
#includewindows.h
#includestring.h
void Print(std::string szBuffer,int nCount)
{for (size_t i 0; i nCount; i){std::cout szBuffer : i std::endl;}
}
int main()
{std::thread obj(Print,abc,200);system(“pause”);return 0;
}程序运行发现 原因这就是时间切片的伪并发可能出现的问题很形象展示了线程同步问题这个现象
现我们针对如下线程同步程序进行进一步的问题解决讲解
#include iostream
#include thread
int g_Value 0;
void add()
{for (size_t i 0; i 1000000; i){g_Value;}
}
int main()
{std::thread objA(add);std::thread objB(add);objA.join();objB.join();std::cout g_Value std::endl;system(pause);return 0;
}程序运行以后g_Value的最终结果应该是2000000但但每次运行时g_Value都是随机数这是因为在线程同步时出现丢失操作
互斥体解决线程同步问题
方法一使用互斥体方法
#include iostream
#include thread
#includemutex
int g_Value 0;
std::mutex some_mutex; //声明一个互斥体,用于线程可能出错的地方
void add()
{for (size_t i 0; i 1000000; i){some_mutex.lock(); //该函数被互斥体加锁保护。当一个线程在访问该函数时其他线程无法访问g_Value; some_mutex.unlocke(); //互斥体解锁}
}//此时该函数不会再出现多线程同时访问的问题了
int main()
{std::thread objA(add);std::thread objB(add);objA.join();objB.join();std::cout g_Value std::endl;system(pause);return 0;
}方法二使用锁类模板
#include iostream
#include thread
#includemutex
int g_Value 0;
void add()
{for (size_t i 0; i 1000000; i){//构造函数调用时加锁析构函数调用时解锁std::lock_guardstd::mutex guard(some_mutex); g_Value;}
}
int main()
{std::thread objA(add);std::thread objB(add);objA.join();objB.join();std::cout g_Value std::endl;system(pause);return 0;
}
以上两种方法可以很好的解决线程同步问题
作业
01.尝试使用多线程造成线程同步问题。 02.尝试使用thread库中的其他控制函数
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/84148.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!