栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

学习笔记-----线程和锁(一)

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

学习笔记-----线程和锁(一)

线程thread

————————————————————————————————————————————————————————

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才能实现功能

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/960807.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号