1.一个类重写了operator(),可以f()—相当于匿名对象—f()()相当于调用operator()函数 把对象名当成函数名来使用--伪函数
2.通过成员函数创建多线程
a) 可以用成员函数去实现多进程
多线程最好函数不要重名
利用成员函数构建多线程
毕竟成员函数是共享的
b) thread th3(&fun::run2, f1, "xuxu","hello");
成员函数,调用的对象,参数
- 继承thread:对于继承含有模板的类的套路:
线程也是可以初始化的,不同于函数指针的是:他自己本省就含有很多成员
关于thread继承,构造函数,把默认的继承了之后,由于thread是可以无限接受参数的,所以应该
是可变参数模板
模板构造函数的套路:
可变参数的参数走法:
首先肯定是用右值去接参
再用std::forwanrd去接
类型 && 跟在类型后
2. 多线程:
a) 目前提供五个头文件以支持多线程:
Atomic提供原子操作 thread 线程模型封装 mutex互斥量 condition_variable 条件变量 future进程通信
std::lock_guard它是与mutex配合使用,把锁放到lock_guard中时,mutex自动上锁,lock_guard析构时,同时把mutex解锁
this_thread::get_id()获取线程id
this_thread::sleep_for(chrono::seconds())
Atomic提供原子操作:定义的原子变量自带锁功能
future进程通信 进一个线程首先要锁lock_guard<mutex>(创建时锁,析构时自动解锁)
set_value()设置值 get_future()才能获取值,要不然只能等
chrono时间函数:this_thread::sleep_for(chrono::seconds(1));跨平台强
5.vector:int*p=myint.get_allocator().allocate(5)/deallocate(p,5);size还是0
Erase insert 第一个参数都是先要起始位置
6. joinable是可会合的意思,一般thread创建的都是可会合的,就是阻塞主线程,让子线程执行完后再继续执行主线程
每个线程执行完后,资源不一定会释放,此时必须调用join()明确指出释放资源
Detach守护线程,与主线程相分离,一旦线程终止释放资源
7.左值引用和右值引用作为参数的区别
左值引用就相当于一般的引用
右值引用:1.具有移动窃取的功能
2.可以把临时对象放进去
Mutex: std::recursive_mutex递归上锁(像多重指针解锁一样)
try_lock()尝试上锁,即使已经被别的线程锁了也不会阻塞,自己锁了再用,就死锁
lock只要别的线程锁了互斥锁就死锁
unique_lock本身还可以用于std::lock参数,因为其具备lock、unlock、try_lock成员函数,这些函数不仅完成针对mutex的操作还要更新mutex的状态。(用自己的lock可以实现多个锁一起锁)
unique_lock在构造时不必对mutex加锁且可以在后期某个时候对mutex加锁; unique_lock可以在自己实例销毁前调用unique_lock::unlock()提前释放锁(有点自带加锁解锁的功效)
线程交换swap和移动move
Future和condition_variable都是线程之间的通信,
Future是set_value才能get()
condition_variable是wait和notify_all