c++封装线程

原创 2015年07月29日 17:17:07

线程

(1)Linux线程库有两个流行的线程库,分别是LinuxThreads和NPTL,由于LinuxThreads的某些缺点,已经被NPTL取代,它们都是基于1:1模式实现,即1个用户线程被映射为1个内核线程;故每一个用户线程在内核中有唯一的标识

线程标识

使用pthread_t有问题!!!

void* loop(void*)  
{  
  cout  << "Thread run" << endl;  
  return NULL;  
}  
  
int main()  
{  
  pthread_t t1, t2;  
  
  errno = pthread_create(&t1, NULL, loop, NULL);  
  assert(!errno);  
  pthread_join(t1, NULL);  
  
  pthread_create(&t2, NULL, loop, NULL);  
  assert(!errno);  
  pthread_join(t2, NULL);  
  
  cout  << hex << t1 << " " << t2 << endl;  
  
  return 0;  
}  

说明几点:

(1)验证该代码片段可得:上述t1和t2值相同;Pthreads只能保证同一进程中各线程pthread_t在同一时刻不同,不能保证同一线程具有不同的id;

(2)pthread_t在某些应用场合不能作为线程的标识,比如一个线程已经死亡,而此时创建一个新的线程,可能重用了旧的pthread_t,导致本来与旧线程交互的数据,开始又和新的线程错误执行;

(3)解决办法:由于NPTL基于1:1模式(1个用户线程被映射为1个内核线程)实现;故每一个用户线程在内核中也有唯一的标识,使用gettid()可以获得该标识,为了减少系统调用次数,可使用__thread进行缓存该id,这样只有第一次使用该id才会调用gettid()系统调用,但是可移植性会降低;下述代码中__thread缓存tid;syscall(SYS_gettid)为直接使用系统调用号执行系统调用,即直接获取某执行线程的唯一线程ID;

实现代码如下:

namespace CurrentThread  
{  
  
pid_t gettid()  
{  
  return syscall(SYS_gettid);  
}  
  
__thread pid_t t_tid;  
  
static pthread_t tid()  
{  
  if (t_tid == 0)  
    {  
      t_tid = gettid();  
    }  
  
  return t_tid;  
}  
  
}  

  1. thread声明如下:
  1. namespace CurrentThread  
    {  
      
    extern __thread pid_t t_tid;  
    extern pid_t tid();  
      
    }  
      
    //notice: we should make Thread object's life longer than thread, so we shold always use fun: join,  
    class Thread final  
    {  
    public:  
      Thread(const Thread&) = delete;  
      Thread& operator=(const Thread&) = delete;  
      
      typedef std::function<void()> ThreadFunc;  
      
      explicit Thread(const ThreadFunc& func);  
      
      void start();  
      
      bool running() const  
      {  
        return _running;  
      }  
      
      int join()  
      {  
        int err = pthread_join(_threadId, NULL);  
        return err;  
      }  
      
      pid_t tid() const  
      {  
        return _tid;  
      }  
      
    private:  
      void _runInThread();  
      static void* _threadFunc(void*);  
      
      pid_t _tid;  
      pthread_t _threadId;  
      ThreadFunc _func;  
      bool _running;  
    };  

说明几点:

(1)_tid为线程的唯一标识,也就是利用上述CurrentThread和__thread来实现获得的;

(2)线程与Thread对象的生命周期,要注意Thread对象析构和线程终止的顺序关系;当调用thread.join()函数时,可以保证Thread对象在线程终止之后析构;若没有调用thread.join()函数,将会出现thread先析构的情况,此时C++析构会自动deatch线程,因此保证资源不会泄漏,但是线程在使用继续使用Thread相关资源时,执行过程将会出现未定义情况;因此我们应该保证使用thread.join()函数,即Thread的生命周期要长于线程的生命周期;

thread实现如下:

  1. __thread pid_t  CurrentThread::t_tid = 0;  
      
    pid_t CurrentThread::tid()  
    {  
      if (t_tid == 0)  
        t_tid = syscall(SYS_gettid);  
      
      return t_tid;  
    }  
      
    Thread::Thread(const ThreadFunc& func):  
        _func(func),  
        _running(false)  
    {  
      
    }  
      
    void Thread::start()  
    {  
      assert(!_running);  
      _running = true;  
      
      int err = pthread_create(&_threadId, NULL, Thread::_threadFunc, this);  
      if (err != 0)  
        {  
          cout << "pthread_create system error";  
        }  
    }  
      
    void Thread::_runInThread()  
    {  
      assert(_running);  
      try  
        {  
          _tid = CurrentThread::tid();       //impotant, the time we obtain tid;  
      
          cout << "Thread tid[" << _tid << "] is threadFunc";  
      
          if (_func)  
            _func();  
        }  
      catch (...)  
        {  
          cout << "Exception happen in Thread";  
        }  
    }  
      
    void* Thread::_threadFunc(void* obj)      //remember obj's scope in self class  
    {  
      Thread* thread = static_cast<Thread*>(obj);  
      thread->_runInThread();  
      return NULL;  
    }  

说明几点:

(1)static void* _threadFunc(void*)为Thread的static成员函数,而不是成员函数,因为pthread_create(&_threadId, NULL, Thread::_threadFunc, this)接收的函数类型必须是一个类似全局的函数,使用非static成员函数,显然我们还要传递相对应的对象指针,pthread_create是无法接收的;
(2)在_runInThread()中,使用 catch (...)捕捉线程执行过程中的一切异常;
测试代码:
  1. #include <Base/Thread.h>  
    #include <stdio.h>  
      
    using namespace std;  
    using namespace Base;  
      
    void func1() {  
      printf("%s %d\n", "func1: tid", CurrentThread::tid());  
    }  
      
    void func2() {  
       printf("%s %d\n", "func2: tid", CurrentThread::tid());  
    }  
      
    int main(void) {  
      Thread thread1(func1);  
      Thread thread2(func2);  
        
      thread1.start();  
      thread2.start();  
        
      thread1.join();  
      thread2.join();  
      return 0;  
    }  





版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/linuxcprimerapue/article/details/47130887

C++封装线程类

/** \file * Thread.h,定义线程创建和停止接口,通过内联函数提供给其它模块使用 * * \author Fzuim * * 版本历史 * \par 2014-7-7 * * * ...
  • fzuim
  • fzuim
  • 2017-04-10 16:05:49
  • 506

linux C++ 面向对象线程类封装

1.封装遇到的问题 将pthread线程封装为抽象类,这样用户在使用线程时,只需要继承一下这个抽象类,并实现相应的接口就可以了。这样做的好处是 用户可以将注意力集中在线程所要执行的逻辑上,而不需要关注...
  • maotoula
  • maotoula
  • 2016-11-25 17:01:00
  • 11212

muduo 之线程(13)

线程的标示 线程标识符     pthread_self gettid     __thread,gcc内置的线程局部存储设施     __thread只能修饰POD类型 POD类型(plain ol...
  • laohan_
  • laohan_
  • 2013-11-06 17:07:59
  • 1905

C++中面向对象和基于对象的线程封装方法

原文链接:http://blog.chinaunix.net/uid-26611383-id-4273854.html
  • yuanhubilie
  • yuanhubilie
  • 2014-07-11 11:11:27
  • 2005

C++线程的高级封装, 支持对类成员函数开启线程

  • 2014年04月16日 07:10
  • 2KB
  • 下载

C++ 封装的多线程类

在JAVA中,实现多线程有两种方式,一种是继承自Thread类,一种是Runnable,在MFC中也有CWinThread类,但是我们如何利用已有的多线程的机制来实现一个多线程类呢? 在Wind...
  • netanimals
  • netanimals
  • 2011-08-03 19:09:26
  • 4452

c++11 thread 封装线程类

c++ thread也挺好用的,也可以像qt thread那样,start启动,run函数为线程的实际运行代码。thread和this_thread方法不多,常用的就几个。 1.std::t...
  • eric0095
  • eric0095
  • 2016-01-21 11:01:38
  • 1626

linux下的c++ 多线程封装

最近为了学习linux 下的多线程,自己用c++封装了一个简易的局域网多线程聊天服务器,期间遇到了一些坑写到这里与大家共勉! 主要功能: 封装了一个名叫pthread_serv的类对每一个客户端的响...
  • your_eyes_see_sea
  • your_eyes_see_sea
  • 2017-03-04 00:53:19
  • 252

c++类和类的封装,对象线程封装

c++类和类的封装,对象线程封装C++面向对象编程介绍 面向对象编程(Object Oriented Programming),简称OOP。 在传统的面向过程编程中,数据以及数据的相关操作函数都是分离...
  • h674174380
  • h674174380
  • 2017-07-30 09:18:02
  • 680

C++封装POSIX 线程库(三)线程的封装

POSIX线程的C++封装
  • zhangxiao93
  • zhangxiao93
  • 2016-07-26 22:43:55
  • 901
收藏助手
不良信息举报
您举报文章:c++封装线程
举报原因:
原因补充:

(最多只允许输入30个字)