做的网站里面显示乱码怎么解决,做农产品网站,网站建设一般多少钱方案,淘宝的网站怎么做的好文章目录 一、线程的基本管控1.1发起线程1.2等待线程完成1.3出现异常情况下等待1.4后台运行线程 二、向线程函数传递参数三、转移线程归属权四、运行时选择线程数量五、识别线程六、总结七、参考书籍 一、线程的基本管控
1.1发起线程
线程通过构建std::thread对象而启动… 文章目录 一、线程的基本管控1.1发起线程1.2等待线程完成1.3出现异常情况下等待1.4后台运行线程 二、向线程函数传递参数三、转移线程归属权四、运行时选择线程数量五、识别线程六、总结七、参考书籍 一、线程的基本管控
1.1发起线程
线程通过构建std::thread对象而启动该对象指明线程要运行的任务。 举一个简单的栗子
#include iostream
#include thread // 线程函数
void threadFunction() { for (int i 0; i 10; i) { std::cout Thread function executing... std::endl; }
}
int main() { // 创建线程并启动 std::thread t(threadFunction); // 等待线程完成 t.join(); return 0;
}1.2等待线程完成
若需要等待线程完成那么可以在与之关联的std::thread实例上通过调用成员函数join()实现。除了join()还可以对线程进行判断joinable()。 举一个简单的栗子
#include iostream
#include thread void threadFunction() { std::cout Thread function executing... std::endl;
} int main() { // 创建线程并启动 std::thread t(threadFunction); // 检查线程是否可joinable if (t.joinable()) { // 等待线程完成 t.join(); } else { std::cout Thread is not joinable. std::endl; } return 0;
}1.3出现异常情况下等待
当然程序在运行时可能会出一些意外情况。为了防止因抛出异常而导致的应用程序终结我们需要决定如何处理这种情况。 举一个简单的栗子
#include iostream
#include thread
#include mutex
#include condition_variable std::mutex mtx;
std::condition_variable cv;
bool ready false; void workerThread() { try { // 模拟线程执行过程中可能会出现的问题 std::this_thread::sleep_for(std::chrono::seconds(1)); mtx.lock(); ready true; cv.notify_one(); mtx.unlock(); } catch (const std::exception e) { std::cout Thread caught exception: e.what() std::endl; }
} int main() { std::thread t(workerThread); t.detach(); // 分离线程使其在后台运行 // 主线程等待子线程完成 std::unique_lockstd::mutex lock(mtx); cv.wait(lock, []{ return ready; }); std::cout Thread finished. std::endl; return 0;
}1.4后台运行线程
std::thread::detach 是 C11 标准库中 头文件提供的一个函数用于将线程对象与其底层线程分离。一旦线程被分离当它结束时其资源会自动被回收而不需要通过 std::thread::join 进行显式等待。 当调用 detach 之后该 std::thread 对象将不再代表一个活动线程并且无法再被 join。如果尝试对已分离的线程调用 join程序会抛出一个 std::system_error 异常。 举个简单的栗子
#include iostream
#include thread
#include chrono void threadFunction() { for (int i 0; i 5; i) { std::this_thread::sleep_for(std::chrono::seconds(1)); std::cout Thread function executing... std::endl; }
} int main() { // 创建线程并启动 std::thread t(threadFunction); // 分离线程使其在后台运行 t.detach(); // 主线程继续执行其他任务 for (int i 0; i 5; i) { std::this_thread::sleep_for(std::chrono::seconds(1)); std::cout Main thread executing... std::endl; } return 0;
}detach函数使用注意事项
线程资源管理detach函数将线程与主线程分离这意味着主线程不再负责等待该线程的完成。一旦线程被分离它的资源将由运行时库负责清理。因此如果主线程在后台线程完成之前结束那么后台线程可能会变成“僵尸线程”这可能导致资源泄漏或其他问题。线程安全使用detach时需要注意线程安全。如果多个线程同时操作同一个数据结构而其中一个线程调用了detach那么这个数据结构可能会在未同步的情况下被修改导致数据不一致或其他问题。异常处理如果在线程函数中抛出了异常而该异常未被捕获和处理那么当线程结束时该异常可能会被抛出并导致程序崩溃。因此在使用detach时需要确保线程函数中的异常被正确处理。joinable检查在调用detach之前最好先检查线程是否可以被join。如果线程已经被join或detach过再次调用detach会导致未定义的行为。
二、向线程函数传递参数
若要向新线程上的函数或可调用对象传递参数方法相当简单直接向std::thread的构造函数添加更多参数即可。 举个简单的栗子
#include iostream
#include thread // 这是线程函数接受一个整数参数
void threadFunction(int param) { std::cout Thread function received: param std::endl;
} int main() { // 创建一个线程并传递参数 std::thread t(threadFunction, 42); // 等待线程完成 t.join(); return 0;
}向线程传递参数的注意点 向线程函数传递参数时需要注意以下几点
参数类型匹配确保传递给线程函数的参数类型与函数期望的参数类型匹配。否则可能会导致编译错误或运行时错误。参数的拷贝语义在传递参数时要注意参数的拷贝语义。如果传递的是大型对象或可变对象可能会导致不必要的内存分配和拷贝。可以使用引用或指针来避免不必要的拷贝。线程安全如果多个线程同时访问和修改共享数据需要确保线程安全。可以使用互斥锁、条件变量等同步机制来保护共享数据。异常处理如果线程函数可能抛出异常需要确保异常能够被正确处理。可以使用try-catch语句块来捕获并处理异常。参数的传递方式可以使用值传递、引用传递或指针传递等方式传递参数。需要根据具体情况选择合适的传递方式以避免不必要的拷贝和内存分配。线程函数的返回值如果线程函数有返回值需要确保返回值的正确性和线程安全性。可以使用std::future或std::async等机制来获取线程函数的返回值。
总之向线程函数传递参数时需要注意参数的类型、拷贝语义、线程安全、异常处理、传递方式和返回值等问题以确保程序的正确性和性能。
三、转移线程归属权
线程运行的过程中会有出现线程归属权需要进行转移的情况 1编写函数创建线程线程置于后台运行但函数本身不等待线程完成将这个线程的归属权向上移交给函数的调用者 2想创建一个线程将其归属权传入某个函数由他负责等待该线程结束 要想实现线程归属权的转移可以使用std::move函数来实现 举个简单的栗子
#include iostream
#include threadvoid threadFunction(){//线程中执行的函数std::cout Thread is runnning! std::endl;
}
int main(){//创建一个线程std::thread myThread(threadFunction);//转移线程所有权std::thread anotherThread std::move(myThread);//等待另一个线程执行完毕anotherThread.join();return 0;//此时myThread不再拥有线程的所有权不能再join,//myThread.join();这一行会导致编译错误
}四、运行时选择线程数量
通过hardware_concurrency() 来确定系统上可以并发执行的线程数。 std::thread::hardware_concurrency() 是 C11 标准库中的一个函数它返回一个无符号整数表示在给定的系统上可以并发执行的线程数。这个数字通常表示系统的核心数或逻辑处理器数。 这个函数在编程中有多种用途 1线程数量选择当你需要并行执行多个任务时可以使用 std::thread::hardware_concurrency() 来确定最适合的线程数量。这通常是一个合理的起点但你仍然需要考虑其他因素如任务的工作负载、内存使用情况等。 2资源利用通过使用与系统核心数相匹配的线程数可以更有效地利用系统资源。过多的线程可能会导致上下文切换的开销增加而太少的线程则可能无法充分利用系统资源。 3性能测试在测试多线程应用程序的性能时可以使用 std::thread::hardware_concurrency() 来确定基准线程数。然后可以逐渐增加或减少线程数量以观察性能的变化。 举个简单的栗子
#include iostream
#include thread
#include vector // 简单的任务函数
void simpleTask(int threadId) { std::cout Thread threadId is running. std::endl;
} int main() { // 获取系统的最大并发线程数 unsigned int maxConcurrentThreads std::thread::hardware_concurrency(); std::cout Maximum concurrent threads: maxConcurrentThreads std::endl; // 创建线程的向量 std::vectorstd::thread threads(maxConcurrentThreads); // 启动线程并为其分配简单的任务 for (int i 0; i maxConcurrentThreads; i) { threads[i] std::thread(simpleTask, i); } // 等待所有线程完成 for (auto thread : threads) { thread.join(); } std::cout All threads completed. std::endl; return 0;
}五、识别线程
在C多线程编程中有2种方式能获取线程。 1在与线程关联的std::thread对象上调用成员函数get_id(),就可以获得该线程ID; 2当前线程的ID可以通过调用std::this_thread::get_id()方法便可以获得。 举个简单的栗子
#include iostream
#include thread
//延时函数
void delay(int milliseconds) {std::this_thread::sleep_for(std::chrono::milliseconds(milliseconds));
}
//方法一调用成员函数std::this_thread::get_id()返回当前线程的ID
void print_id(){std::cout std::this_thread::get_id() std::endl;delay(100);
}
void hello_world(){std::cout Hello world! std::endl;
}
int main(){std::thread t1(print_id);std::thread t2(hello_world);//方法二在与线程关联的std::thread对象上调用成员函数get_id()std::cout t2_id: t2.get_id() std::endl;t1.join();t2.join();
}六、总结
书山有路勤为径学海无涯苦作舟。
七、参考书籍
《C并发编程实战第二版》