————————————————————————————————————————————————————————
detach和join函数C++多线程和detach相对的函数有join,join的意思是父线程等待子线程结束,而detach的含义是主线程和子线程相互分离,互不干扰。
-使用join使用join函数,当子线程循环执行或者执行时间长于主线程时,主线程会等待子线程结束再结束。
class Resource{ //资源测试类
public:
Resource(int n){
std::cout<<"get resource."<
std::cout<<"free resource."< //线程函数
// while (true){
Resource resource(5);
std::cout<<"thread start."< //主线程
std::cout<<"main thread start."<
运行结果为:
main thread start.
get resource.
the value is :5
thread start.
free resource.
主线程等子线程对象析构之后才结束,如果子线程函数为死循环时,则主线程会一直阻塞等待子线程结束。显而易见的使用join函数的缺点为可能造成主线程卡死。
- 使用detach
使用detach函数,会将子线程与主线程剥离开,即子线程的生存周期不会对主线程产生影响,对于像车辆一样对安全要求较高的进程来说这是比较重要的。
改为
resourceTestThread.detach();
后,进程的运行结果为:
main thread start.
get resource.
the value is :5
thread start.
可以看到主线程并不会等到子线程对象的析构,而直接结束。 所以使用detach的缺点为,可能会存在未释放的资源。所以,可以考虑这种情况,如果两子线程公用一把锁,主线程提前结束当前周期,会存在子线程锁未释放的情况,如果此时终止线程则会使另一个子线程死锁。但是正常循环的话,没发现太大问题,子线程1释放锁的一瞬间会被子线程2拿到。思路来源
使用detach后,在子线程加锁测试
有趣的现象来了。将子线程函数加锁,主线程循环执行后。
class Resource{
public:
Resource(int n){
std::cout<<"get resource."<
std::cout<<"free resource."<
// while (true){
a++;
testMutex.lock();
std::cout<<"thread1 mutex lock time:"<
// while (true){
Resource resource(n);
std::cout<<"thread2 start."<
while (true){
std::cout<<"main thread start."<
运行结果为:
main thread start.
thread1 mutex lock time:1
get resource.
thread1 start.
main thread start.
thread1 mutex unlock time:2
free resource.
thread1 mutex lock time:2
get resource.
thread1 start.
main thread start.
thread1 mutex unlock time:3
free resource.
thread1 mutex lock time:3
get resource.
thread1 start.
main thread start.
thread1 mutex unlock time:4
free resource.
thread1 mutex lock time:4
get resource.
thread1 start.
main thread start.
thread1 mutex unlock time:5
free resource.
thread1 mutex lock time:5
get resource.
thread1 start.
main thread start.
main thread start.
thread1 mutex lock time:6
get resource.
thread1 start.
thread1 mutex unlock time:6
free resource.
main thread start.
thread1 mutex unlock time:8
free resource.
thread1 mutex lock time:8
get resource.
thread1 start.
main thread start.
thread1 mutex unlock time:9
free resource.
thread1 mutex lock time:9
get resource.
thread1 start.
main thread start.
thread1 mutex unlock time:10
free resource.
main thread start.
thread1 mutex lock time:10
get resource.
thread1 start.
main thread start.
thread1 mutex unlock time:12
free resource.
thread1 mutex lock time:12
get resource.
thread1 start.
main thread start.
thread1 mutex unlock time:13
free resource.
thread1 mutex lock time:13
get resource.
thread1 start.
main thread start.
thread1 mutex unlock time:14
free resource.
thread1 mutex lock time:14
get resource.
thread1 start.
main thread start.
thread1 mutex unlock time:15
free resource.
thread1 mutex lock time:15
get resource.
thread1 start.
main thread start.
main thread start.
thread1 mutex unlock time:16
free resource.
thread1 mutex lock time:16
get resource.
thread1 start.
main thread start.
thread1 mutex unlock time:18
free resource.
thread1 mutex lock time:18
get resource.
thread1 start.
main thread start.
thread1 mutex unlock time:19
free resource.
thread1 mutex lock time:19
get resource.
thread1 start.
main thread start.
thread1 mutex unlock time:20
free resource.
thread1 mutex lock time:20
get resource.
thread1 start.
main thread start.
main thread start.
thread1 mutex lock time:thread1 mutex unlock time:21
get resource.
thread1 start.
21
free resource.
main thread start.
thread1 mutex unlock time:23
free resource.
thread1 mutex lock time:23
get resource.
thread1 start.
main thread start.
main thread start.
thread1 mutex lock time:24
get resource.
thread1 start.
thread1 mutex unlock time:24
free resource.
有点乱了。。。 把a++放到锁里面,执行是正常的。
看起来像是第一个主线程周期子线程1未解锁,由于资源还未释放,第二个主线程周期进来,运行完上锁之前的程序段,然后继续执行锁里的顺序,先把锁解了又上的锁。 改成 try_lock后就正常了(try_lock执行完之后不对返回值进行处理他是继续往下执行的!!!),除了第一周期未解锁。 用join函数就不会出现这个问题,这也是二者的优缺点之一。
两个子线程的情况也是这样,子线程2会在子线程1释放的瞬间拿到锁。
———————————————————————————————————————————————————————
std::ref函数
- std::ref主要在函数式编程(如std::bind)时使用,bind是对参数直接拷贝,无法传入引用(即使你传入的实参是引用类型也不行),故引入std::ref()。使用std::ref可以在模板传参的时候传入引用。
- 不仅仅是在使用bind时,在使用thread进行编程时,也会发生这样的问题,thread的方法传递引用的时候,必须用ref来进行引用传递,否则就是浅拷贝。
还是利用上面的测试函数,
void testThread1(int& n){
// while (true){
a++;
// pthread_mutex_lock(&testMutex);
// std::unique_lock mtx(testMutex);
testMutex.try_lock();
gettimeofday(&timenow,NULL);
std::cout<<"thread1 mutex lock time:"<
// while (true){
b++;
// std::unique_lock mtx(testMutex);
testMutex.try_lock();
gettimeofday(&timenow,NULL);
std::cout<<"thread2 mutex lock time:"<
// pthread_mutexattr_init(&mutexattr);
// pthread_mutexattr_settype(&mutexattr,PTHREAD_MUTEX_RECURSIVE_NP);
// pthread_mutex_init(&testMutex,&mutexattr);
// while (true){
gettimeofday(×tart,NULL);
int bbb =1;
//for(int aa=0;aa<2;aa++){
std::cout<<"main thread start time: "< mtx(testMutex);
std::cout<<"value bbb : "<
注意!!!
1、由于是开线程测试,主线程和子线程同步执行,所以需要再打印bbb前面加个延时,否则也是主线程先拿到锁,那么打印出来的就是1,需要等子线程先赋值完毕,做其他应用的时候也要考虑到这一点。
2、由于想做到引用,所以子线程的函数形参也必须是引用!!配合ref才能实现功能



