赞
踩
线程的定义(维基百科):线程(英语:thread)是操作系统能够进行运算调度的最小单位。大部分情况下,它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。在Unix System V及SunOS中也被称为轻量进程(lightweight processes),但轻量进程更多指内核线程(kernel thread),而把用户线程(user thread)称为线程。
每个线程都包含表示执行环境所必需的信息:包括进程中标识线程的线程ID、一组寄存器值、栈、调度优先级和策略、信号屏蔽字、errno变量以及线程私有数据。
一个进程的所有信息对该进程的所有线程是共享的。
#include <iostream> #include <thread> void FuncFirst() { std::cout << "this is FuncFirst" << std::endl; } void FuncSecond(int val) { std::cout << "this is FuncSecond, and val: " << val << std::endl; } int main() { std::thread _th1(FuncFirst); std::thread _th2(FuncSecond, 1); std::thread _th3([]{ std::cout << "lambda without param" << std::endl; }); std::thread _th4([](int val){ std::cout << "lambda with param: " << val << std::endl;}, 10); _th1.join(); //等待_th1线程结束 _th2.join(); _th3.join(); _th4.join(); return 0; }
#include <iostream> #include <thread> void FuncFirst() { std::cout << "this is FuncFirst" << std::endl; } void FuncSecond(int val) { std::cout << "this is FuncSecond, and val: " << val << std::endl; } int main() { std::thread _th1(FuncFirst); std::thread _th2(FuncSecond, 1); std::thread _th3([]{ std::cout << "lambda without param" << std::endl; }); std::thread _th4([](int val){ std::cout << "lambda with param: " << val << std::endl;}, 10); std::cout << "_th1 id: " << _th1.get_id() << std::endl; std::cout << "_th2 id: " << _th2.get_id() << std::endl; std::cout << "_th3 id: " << _th3.get_id() << std::endl; std::cout << "_th4 id: " << _th4.get_id() << std::endl; _th1.join(); _th2.join(); _th3.join(); _th4.join(); std::cout << "main thread id: " << std::this_thread::get_id() << std::endl; return 0; }
确保同一时间只有一个线程访问数据,在访问共享资源前对互斥量进行加锁,在访问完成后释放互斥量。
std::mutex位于头文件中,主要使用的成员函数为lock、try_lock、unlock.
#include <iostream> #include <thread> #include <mutex> std::mutex mutex_; int g_val = 0; void func() { mutex_.lock(); //mutex_.try_lock(); ++g_val; mutex_.unlock(); } int main() { std::thread _th1([]{ for (int i = 0; i < 10000; ++i) { func(); } }); std::thread _th2([]{ for (int i = 0; i < 10000; ++i) { func(); } }); _th1.join(); _th2.join(); std::cout << "g_val: " << g_val << std::endl; return 0; }
如果自己手动加锁和解锁,经常会出现加了锁,但是忘记解锁的情况,所以一般mutex都会配合lock_guard或者unique_lock使用。
#include <iostream> #include <mutex> #include <thread> std::mutex mutex_; int g_val = 0; int main() { std::thread _th1([]{ // 不加锁,最后会出现g_val != 200000 std::lock_guard<std::mutex> lock(mutex_); for (int i = 0; i < 100000; ++i) { ++g_val; } }); std::thread _th2([]{ std::lock_guard<std::mutex> lock(mutex_); for (int i = 0; i < 100000; ++i) { ++g_val; } }); _th1.join(); _th2.join(); std::cout << "g_val: " << g_val << std::endl; return 0; }
读写锁在c++17的shared_mutex支持。
对shared_mutex使用lock_guard或者unique_lock就是写锁。
对shared_mutex使用lock_shared或者unlock_shared就是读锁。
// TODO
std::condition_variable位于<condition_variable>头文件中。
等待有三个函数:
通知有两个函数:
#include <iostream> #include <thread> #include <condition_variable> #include <mutex> #include <chrono> std::mutex mutex_; std::condition_variable cv_; void thread_a() { std::unique_lock<std::mutex> lock(mutex_); cv_.wait(lock); std::cout << "this is thread_a" << std::endl; } void thread_b() { std::cout << "this is thread_b and will sleep 2 s" << std::endl; std::this_thread::sleep_for(std::chrono::seconds(2)); cv_.notify_all(); } int main() { std::thread _th1(thread_a); std::thread _th2(thread_b); _th1.join(); _th2.join(); return 0; }
自旋锁与mutex类似,自旋锁在没有获得锁之前会一直处于忙等的状态。
C++没有提供自旋锁,但是可以使用C++11的原子变量实现自旋锁。
#ifndef __SPIN_LOCK_H__ #define __SPIN_LOCK_H__ #include <atomic> namespace dailyrecord { class SpinLock { public: SpinLock() : atomic_bool_(false) { } void lock() { bool cmp = false; while (!atomic_bool_.compare_exchange_weak(cmp, true)) { // atomic_bool_与cmp比较,如果相等,则atomic_bool_的值被true替换 // 如果不相等,则cmp的值被atomic_bool_的值替换,所以需要重新给cmp赋值 cmp = false; } } void unlock() { atomic_bool_.store(false); } private: std::atomic_bool atomic_bool_; }; } //namespace dailyrecord #endif __SPIN_LOCK_H__
目前C++标准还不支持,boost有支持。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。