# if 0
#include <iostream>
#include <thread>
using namespace std;
// 线程库
/*
在C++11之前,涉及到多线程问题,都是和平台相关的
*/
/*
* thread() 构造一个线程对象,没有关联任何线程函数,即没有启动任何线程
* thread(fn,arg1,arg2,...) 构造一个线程对象,并关联线程函数fn,arg1,arg2..为线程函数的参数
* get_id() 获取线程id
* jionable() 线程是否还在执行,joinable 代表的是一个正在执行中的线程
* jion() 函数在调用后会阻塞住线程,当该线程结束后,主线程继续执行
* detach() 在线程创建线程对象后马上调用,用于把被创建线成于线程对象分离,所为线程分离
*
*/
// 注意:
// 1.线程是操作系统中的一个概念,线程对象可以关联一个线程,用来控制线程以及获取线程的状态
// 2.当创建线程对象后,没有提供线程函数,该对象实际没有对应任何线程
#if 0
int main() {
std::thread t1;
std::cout << t1.get_id() << std::endl;
return 0;
}
#endif
// get_id() 返回值为id类型,id类型实际为std::thread 命名空间下封装的一个类,该类中包含一个结构体
#if 0
typedef struct {
void* _Hnd;
unsigned int _Id;
} _Thrd_imp_t;
#endif
// 3. 当创建一个线程后,并给线程关联线程函数,该线程就被启动,与主线程一起运行。
// 线程函数可以由以下三种方式提供
// (1) 函数指针
// (2) lambda 表达式
// (3) 函数对象(仿函数)
// 4. thread类是防拷贝的,不允许拷贝以及赋值,但是可以移动构造和移动赋值,及将一个线程对象关联线程的状态转移给其他线程对象,转移期间不影响线程执行
// 5. 可以通过 jionable() 函数判断线程是否是有效的,如果是以下任意情况,则线程无效
// (1)采用无参构造函数构造的线程对象
// (2) 线程对象的状态已经转移给其他线程对象
// (3) 线程已近调用join 或者 detach 结束
// 线程函数参数
// 线程函数的参数是以值拷贝的方式拷贝到线程栈空间中的。 因此: 即使线程参数为引用参数,在线程中修改后也不能修改外部实参
// 因为其实际引用的是线程栈中的拷贝,而不是外部实参。
#if 0
void ThreadFun1(int& x){
x += 10;
}
void ThreadFun2(int* x) {
*x += 10;
}
int main() {
int a = 10;
// 在线程函数中对 a进行修改,不会影响外部实参,因为:线程参数虽然是引用方式,但其实际引用的是线程中的拷贝
thread t1(ThreadFun1, a);
t1.join();
cout << a << endl;
// 如果想要通过形参改变外部实参时,必须借助 std::ref()函数
thread t2(ThreadFun1, ref(a));
t2.join();
cout << a << endl;
// 地址拷贝
thread t3(ThreadFun2, &a);
t3.join();
cout << a << endl;
return 0;
}
#endif
// 如果类成员函数作为线程参数时,必须将this作为线程函数参数!
// join 与 detach
// 启动一个线程后,当这个线程结束的时候,如何去回收线程所使用的资源呢?
// join() == pthread_wait() : 主线程被阻塞,当新线程终止时,join() 会自动清理相关的线程资源然后返回
// 主线程继续向下执行让后销毁线程对象。 由于join() 清理了线程的相关资源,thread 对象与已销毁的线程就没有关系了
// 因此一个线程对象只能调用一次join() 否则程序崩溃!
// 注意线程回收问题!
// detach() == pthread_detach() 线程分离,线程结束后也不会通知主线程。线程结束后资源能正确回收。
// 原子操作 && 锁
#if 0
int main() {
cout << "sb" << endl;
return 0;
}
#endif
// 原子性操作库!
// #include <mutex>
// #include <atomic> 原子类库!
#include <atomic>
// 可以使用atomic 模板,定义出需要的任意原子类型!
atomic<string> t;
// 锁 C++11 中,采用RALL的方式对锁进行了封装,及lock_guard 和 unique_lock。
// mutex 是不可重入锁.
// lock() :上锁,锁住互斥量 阻塞上锁!
// unlock() : 解锁,释放互斥量的所有权!
// try_lock() :尝试锁住互斥量,如果互斥量被其他线程所占有,则当前线程不会被阻塞。 如果上锁成功 return true else return false;
// recursive_mutex : 可重入锁.
// timed_mutex : 定时阻塞锁。
// try_lock_for() 接受一个时间范围,表示在这一段时间范围之内线程如果没有获得锁则被阻塞住。
// try_lock_until() 接受一个时间点作为参数,在指定时间未来到前,如果没有获得锁则会被阻塞住,如果此期间其他线程释放了锁,
// 则该线程可以获得对互斥量的锁,如果超时返回false;
// recursive_timed_mutex : 定时可重入阻塞锁。
#endif
自学C++ day12 thread 库
最新推荐文章于 2024-05-29 05:00:00 发布