手把手网站开发,南昌网站建设q479185700惠,商城网站解决方案,网站设计和平面设计手撕线程池:
1.进程:进程就是运行中的程序
2.线程的最大数量取决于CPU的核数
3.创建线程 thread t1;
在使用多线程时#xff0c;由于线程是由上至下走的#xff0c;所以主程序要等待线程全部执行完才能结束否则就会发生报错。通过thread.join()来实现
但是如果在一个比…手撕线程池:
1.进程:进程就是运行中的程序
2.线程的最大数量取决于CPU的核数
3.创建线程 thread t1;
在使用多线程时由于线程是由上至下走的所以主程序要等待线程全部执行完才能结束否则就会发生报错。通过thread.join()来实现
但是如果在一个比较严谨的项目中我们最好在使用join函数的时候先判断一下是不是可以使用join函数可以通过joinable函数来判断 它返回的是一个bool值。
join函数是阻塞的当线程函数没有执行完时整个程序是卡在join函数的位置。
线程函数可以传参数如下图所示: 4.在使用多线程时要注意几个问题:
线程函数中数据未定义的错误
1.传递临时变量的问题:
在传递参数时如果参数是临时变量那么这个程序会报错是无法编译的。所以 我们可以使用ref函数来传递引用类型这样程序就可以正常运行了。 2.传递指针或引用指向局部变量的问题
如下图所示: a是一个局部的变量它只在test上是有效的存放在栈区如果test结束调用return(void 可以隐藏return)a变量的地址就被释放掉了那么线程函数无法取到a的引用所以会报错解决方法就是将a定义成全局变量。 3.传递指针或引用指向已经释放的内存的问题 4.类对象可能被释放掉 所以可以引出智能指针share_ptr来管理这个类的对象防止因为某些原因将对象a释放掉导致地址a的丢失 通过引入指针可以但是最后还是要记得释放指针所占用的内存所以引出了智能指针。 5.如何确定你的线程是线程安全的?
如果多线程的程序每次运行结果与单线程运行结果始终是一样的那么你的线程就是线程安全的
6.互斥量死锁
两个线程相互等待导致的死锁
解决方法就是改变一下获取锁的顺序就好了。 让先获取m的线程m和m2都获取这样就不会出现互相等待的情况了。
7.lock_guard
lock_guard是C标准库中的一种互斥量封装类用于保护共享数据防止多个线程同时访问同一资源而导致的数据竞争的问题。特点如下:
1.当构造函数被调用时该互斥量会被自动锁定。
2.当析构函数被调用时该互斥量会被自动解锁。
std::lock_guard对象不能复制或移动因此他只能在局部作用域中使用。因为在源码中他禁用了拷贝构造和等号。
8.unique_lock
用于管理互斥量mutex的锁定和解锁操作。它提供了比直接使用std::lock_guard更灵活的互斥量管理方式。 函数try_lock_for()可以等待一段时间正常的锁是一直等待的而这个unique_lock可以支持时间到之后就不等了直接返回掉。 9.std::call_once
它是 C 标准库中的一个函数模板用于保证某个函数在多线程环境下仅被调用一次。它与懒汉模式的单例实现等场景密切相关有助于解决多线程中初始化资源时可能出现的多次初始化问题。
10.实现生产者消费者模型: 11.线程池:
emplace_ back和push_back()区别;
push_back()会执行一个拷贝构造它会创建一个临时对象然后将这个临时对象复制或者移动到容器的末尾。
emplace_back直接调用构造函数它直接在容器的末尾就地构造元素避免了创建临时对象的开销如果构造函数的参数可以直接用来初始化对象的话)。
#includeiostream
#includethread
#includefunctional
#includemutex
#includecondition_variable
#includevector
#includequeueclass ThreadPool {
public:ThreadPool(int numThreads) :stop(false) {for (int i 0; i numThreads; i) {threads.emplace_back([this] {//创建并添加一个新的线程。每个线程执行一个 lambda 函数while (true) {std::unique_lockstd::mutex lock(mtx);condition.wait(lock, [this] { return stop || !tasks.empty(); });//使用lambda表达式 如果为false 为空 阻塞在这里//如果为true 代表任务队列不为空 就往下运行if (stop tasks.empty()) {return;}std::functionvoid() task(std::move(tasks.front()));tasks.pop();lock.unlock();task();}});}}~ThreadPool() {{std::unique_lockstd::mutex lock(mtx);stop true;}condition.notify_all();for (std::thread thread : threads) {thread.join();}}templatetypename F, typename... Argsvoid enqueue (F f, Args... args){//...是可变参数包的语法标记表示Args可以接受零个或多个类型参数std::functionvoid() task(std::bind(std::forwardF(f), std::forwardArgs...));{std::unique_lockstd::mutex lock(mtx);tasks.emplace(std::move(task));}condition.notify_one();}
private:std::vectorstd::thread threads;std::queuestd::functionvoid() tasks;std::mutex mtx;std::condition_variable condition;bool stop;
};
int main() {ThreadPool pool(4);for (int i 0; i 8; i) {pool.enqueue([i] {std::cout Task i is running in thread std::this_thread::get_id() std::endl;std::this_thread::sleep_for(std::chrono::seconds(1));std::cout Task i is done std::endl;});}return 0;
}
12.字符串转整形
#includeiostream
#includestringint StrToInt(char* str) {//字符串转整形int number0;while (*str!0) {number number * 10 *str - 0;str;}return number;
}int main() {char* ptr new char[6];//分配能容纳6个字符包括\0的内存strcpy_s(ptr,6,world);std::coutStrToInt(ptr);}