Android unique_ptr与unique_lock的回收机制

高通SSE架构HAL要与底层ADSP Sensor通信,必须获取对应的SUID, 通过构造suid_lookup以及request_suid来建立连接,request成功后会调用callback,callback与主线程是异步的,若主线程结束的早时,构造的资源被回收就会导致callback异常。下面的demo强行造了一个多线程问题,当智能指针unique_ptr会被系统回收,出现值不对,当然真实的比这个复杂的多。

异常代码

#include <thread>
#include <iostream>
#include <stdio.h>
#include <memory>
#include <unistd.h>


/*
 g++ thread.cpp  -std=c++14 -lpthread 

 use -lpthread
 undefined reference to `pthread_create' 
 use g++
 thread.cpp:(.text+0xdb): undefined reference to `std::cout'
 use -std=c++11
 #error This file requires compiler and library support for the ISO C++ 2011 standard. 
 use -std=c++14
 #error: ‘make_unique’ was not declared in this scope 
*/
using namespace std;

void func1(const int i, int* p){
   sleep(1);
   cout << "child thread 引用地址" << &i << endl;
   cout << "child thread 指针地址" << p << endl;
   cout << "child thread val = " << *p << endl;
   //add here 1
}


void test1(){

   unique_ptr<int> p;
   p = make_unique<int>();
   int var = 1;
   *p = 2;

   cout << "main thread 引用地址" << &var << endl;
   cout << "main thread 指针地址" << p.get() <<endl;
   cout << "main thread val = " << *p << endl;
   thread thread1(func1, var, p.get());
   thread1.detach();
   //add here 2

}

int main(){

   test1();
   sleep(1);
   cout << "main thread exit" << endl;

   return 0;
}

分析异常

main thread 引用地址0x7ffdc320fafc
main thread 指针地址0xb45c20
main thread val = 2
child thread 引用地址0x7f3159f0ee4c
child thread 指针地址0xb45c20
child thread val = 0
main thread exit

可以看到传入的变量地址发生变化,中间必然产生拷贝的过程,而传入的指针地址没有发生变化,当子函数test1结束后就会导致unique_ptr p会系统回收,所以就会出现两次打印的值不对的情况

互斥锁机制

std::condition_variable与std::unique_lock的结合使用
互斥量std::mutex、锁对象lock_guard和unique_lock 及 条件变量std::condition_variable
当线程调用信号量的wait的时候,会把锁给打开,这样其他的线程就能执行,当wait函数遇到唤醒函数notify时,线程会由阻塞转为运行状态,此时锁会直接锁上,即使其他线程也被唤醒,也会阻塞,直到第一个被唤醒的线程执行完毕,跳出unique_lock的执行范围。
std::unique_lockstd::mutex lock只有在没上锁的情况下才能被构造,已上锁的不能被构造,一直处于等地状态,等待锁被释放后再构造。

//add here 1
std::unique_lock<std::mutex> lck(mtx);
ready = true;
cv.notify_all();

//add here 2
std::unique_lock<std::mutex> lck(mtx);
while (!ready) cv.wait(lck); //阻塞进程


高通源码中也由很多使用mutex和condition variable结合的例子
vendor/qcom/proprietary/sensors-see/test/ssc_sensor_info/ssc_sensor_info.cpp
vendor/qcom/proprietary/sensors-see/test/sns_client_test_cpp_cmdline_args/src/ssc_connection_reference.cpp
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值