C++11 中使用 std::thread 来创建线程。
一、创建线程
#include <iostream> #include <thread> #include <mutex> /* 函数指针创建线程 */ void thread_func(int size) { std::cout << "thread_func:" << std::this_thread::get_id() << std::endl; for (size_t i = 0; i < size; ++i) { std::cout << "display form thread:" << std::endl; } } /* 仿函数创建线程 */ class DisplayThread { public: void operator()() { std::cout << "DisplayThread:" << std::this_thread::get_id() << std::endl; for (size_t i = 0; i < 10; ++i) { std::cout << "display form display:" << std::endl; } } }; int main() { /* 获取线程ID */ std::cout << "main:" << std::this_thread::get_id() << std::endl; std::thread thread_1(thread_func, 10); for (size_t i = 0; i < 10; ++i) { std::cout << "display form main_1:" << std::endl; } /* 阻塞等待线程结束 */ thread_1.join(); std::thread thread_2((DisplayThread())); /* 线程后台执行,非阻塞 */ thread_2.detach(); /* Lambda函数创建线程 */ std::thread thread_3( [] { std::cout << "thread_3:" << std::this_thread::get_id() << std::endl; for (size_t i = 0; i < 5; ++i) { std::cout << "display form thread_3:" << std::endl; } } ); for (size_t i = 0; i < 5; ++i) { std::cout << "display form main_2:" << std::endl; } thread_3.join(); system("pause"); return 0; }
二、互斥锁的使用
#include <iostream> #include <thread> #include <mutex> void thread_work_1(int& sum) { for (size_t i = 1; i < 5000; ++i) { sum += i; } } void thread_work_2(int& sum) { for (size_t i = 5000; i <= 10000; ++i) { sum += i; } } int main_func() { int sum = 0; for (size_t i = 1; i <= 10000; ++i) { sum += i; } return sum; } int main() { int sum = 0; std::thread t1(thread_work_1, std::ref(sum)); std::thread t2(thread_work_2, std::ref(sum)); t1.join(); t2.join(); std::cout << "thread sum:" << sum << std::endl; std::cout << "main func sum:" << main_func() << std::endl; system("pause"); return 0; }
上述代码是求1-10000的和,我们为了提高效率,创建了两个线程同时去计算[1,5000)的和以及[5000,10001)的和,那么用于计算和的变量都用相同的ans来获取结果。为了区别多线程的计算结果,在主线程中调用main_func函数求的结果与其作比较。
我们发现两次的运算结果并不相同,那么我们可以分析一下原因,因为在计算过程中的sum是一个引用,是他们的共享资源,所以当一个线程正在计算+i的时候,此时还没有运算结束,就被切到了另一个线程中,然后在这个线程中可能会计算了很多次+i的操作,然后再切回那个线程中时,计算结果可能就会覆盖掉另一个线程的计算结果,因此这样求出来的数一定是比正确结果要小的,所以为了避免这种情况的发生,引入了互斥锁。互斥锁的重点在于他是一个锁,简单来说就是我们用锁将两个线程中计算过程分别用mutex锁上,那么当一个线程正在计算的时候,另一个线程就会等待这个计算的完成。大致流程是这样的,当work1准备计算sum+=i的时候,用mutex将线程其锁上,如果此时sum+=i还没有计算完就切到了work2的线程时,就会通过mutex检测到已经被锁上了,那么work2就会在此等待work1的计算完成,当work1的计算完成以后就会把锁解开,然后进行下一步的计算。所以两个线程种的计算过程都是加锁-计算-解锁的过程,这样就不会出现上述所说的那种情况了。
#include <iostream> #include <thread> #include <mutex> void thread_work_1(int& sum, std::mutex& mtx_lock) { for (size_t i = 1; i < 5000; ++i) { mtx_lock.lock(); sum += i; mtx_lock.unlock(); } } void thread_work_2(int& sum, std::mutex& mtx_lock) { for (size_t i = 5000; i <= 10000; ++i) { mtx_lock.lock(); sum += i; mtx_lock.unlock(); } } int main_func() { int sum = 0; for (size_t i = 1; i <= 10000; ++i) { sum += i; } return sum; } int main() { std::mutex mtx_lock; int sum = 0; std::thread t1(thread_work_1, std::ref(sum), std::ref(mtx_lock)); std::thread t2(thread_work_2, std::ref(sum), std::ref(mtx_lock)); t1.join(); t2.join(); std::cout << "thread sum:" << sum << std::endl; std::cout << "main func sum:" << main_func() << std::endl; system("pause"); return 0; }
还有一种是用lock_guard类模板,它的内部结构很简单,只有构造函数和析构函数,所以也很容里理解它的工作原理,在实例化对象时通过构造函数实现了lock,在析构函数中实现了unlock的操作。这样就可以避免忘记unlock的情况,具体的实现看下面的代码:
#include <iostream> #include <thread> #include <mutex> void thread_work_1(int& sum, std::mutex& mtx_lock) { for (size_t i = 1; i < 5000; ++i) { std::lock_guard<std::mutex> mtx_guard(mtx_lock); sum += i; } } void thread_work_2(int& sum, std::mutex& mtx_lock) { for (size_t i = 5000; i <= 10000; ++i) { std::lock_guard<std::mutex> mtx_guard(mtx_lock); sum += i; } } int main_func() { int sum = 0; for (size_t i = 1; i <= 10000; ++i) { sum += i; } return sum; } int main() { std::mutex mtx_lock; int sum = 0; std::thread t1(thread_work_1, std::ref(sum), std::ref(mtx_lock)); std::thread t2(thread_work_2, std::ref(sum), std::ref(mtx_lock)); t1.join(); t2.join(); std::cout << "thread sum:" << sum << std::endl; std::cout << "main func sum:" << main_func() << std::endl; system("pause"); return 0; }
标签:mtx,int,创建,sum,C++,线程,lock,include From: https://www.cnblogs.com/QingYiShouJiuRen/p/17307057.html