The core method of pthread system

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <iostream>
#include <assert.h>
#include <sys/syscall.h>
using namespace std;


class Thread
{
 private:
  pthread_t thd;
  static void *thread(void *argv); //线程函数是一个全局函数
  // static定义的类的成员函数就是一个全局函数。

 public:
  virtual ~Thread(){
    cout << "destructing base class: Thread;" << endl;
  } //指向基类成员的指针如果用来指向派生类,只能调用派生类中的基类成员,
  // 而无法调用派生类新定义的成员,所以要用虚函数进行多态
  int start();
  void stop();
  virtual void* run() = 0;//基类中的纯虚函数
  static pthread_mutex_t counter_lock;  //remain static in derivative class
  static pthread_cond_t counter_nonzero; //remain static in derivative class
  static int x; //remain static in derivative class
};

/*
 * the virtual member data can only be initialized outside of the class
 */
int Thread::x = 0;
pthread_mutex_t Thread::counter_lock = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t Thread::counter_nonzero = PTHREAD_COND_INITIALIZER;
/*
 * the virtual member data can only be initialized outside of the class
 */


int Thread::start()
{
  if(pthread_create(&thd, nullptr, thread, (void *)this) != 0) //创建一个线程,
    // 它要执行的函数必须是static, 不必等线程执行结束就立即返回一个值, 成功为0
  {
    return -1;
  }
  return 0;
}

void Thread::stop()
{
  int err;
  void* tret;
  err = pthread_join(thd, &tret);
  /*
   * 以阻塞的方式等待指定的线程(必须是joinable的)thd结束
   * (线程里面要执行的函数结束了,线程也就结束了;或者线程内部通过函数pthread_exit来实现)
   * 被等待的线程结束后,pthread_join才会返回; 如果线程已经结束,那么pthread_join会立即返回.
   * pthread_join返回后,被等待线程的资源被收回。
   */
  assert (err == 0);
  printf("exit code: %d \n", *(int*)tret);
}

void* Thread::thread(void *arg) //静态成员函数只能访问静态变量或静态函数,通过传递this指针进行调用
{
  printf("create a new thread: with pthreadself %lu, getpid %d, gettid %lu \n",
         pthread_self(), getpid(), syscall(SYS_gettid));
  Thread *thd = (Thread *)arg;
  return thd->run();//指向Mythread对象的this指针,强转成Thread*类型,调用Mythead重定义的基类Thread的虚函数
}

class MyThread1:public Thread
{
 public:
  ~MyThread1(){
    cout << "destructing thread1;" << endl;
  }
  void* run();
};

void* MyThread1::run()
{
  int* status= new int(111);
  int temp;
  pthread_mutex_lock(&counter_lock);
  printf("T1 gets the lock with pthreadself %lu, getpid %d, gettid %lu \n",
         pthread_self(), getpid(), syscall(SYS_gettid));
  while(x == 0) {
    cout << "x=0, so T1 starts waiting and releases the lock" << endl;
    temp = pthread_cond_wait(&counter_nonzero, &counter_lock);  //the function returns code 0
    // only after it's awaken
    cout << "T1 returns from the waiting by the signal, with code " << temp
    << ", and then gets the lock" << endl;
  }
  cout << "x !=0, so T1 can continue to work......" << endl;
  x--;
  cout << "T1 decreases x: " << x << endl;
  cout << "T1 releases the lock" << endl;
  pthread_mutex_unlock(&counter_lock);

  printf("waiting the exit of T1 \n");
  sleep (10);

  cout << "T1 exits" << endl;
  return (void*)status;
  //pthread_exit((void*)status);
}


class MyThread2:public Thread
{
 public:
  ~MyThread2(){
    cout << "destructing thread2;" << endl;
  }
  void* run();
};

void* MyThread2::run()
{
  sleep (2);
  int* status= new int(222);
  pthread_mutex_lock(&Thread::counter_lock);
  printf("T2 gets the lock with pthreadself %lu, getpid %d, gettid %lu \n",
         pthread_self(), getpid(), syscall(SYS_gettid));
  if(x == 0) {
    cout << "T2 signals" << endl;
    pthread_cond_signal(&Thread::counter_nonzero);

    cout << "T2 signaled and then sleeps..." << endl;
    sleep (3);
  }

  x++;
  cout << "T2 increases x: " << x << endl;
  cout << "T2 releases the lock" << endl;
  pthread_mutex_unlock(&Thread::counter_lock);

  cout << "T2 exits" << endl;
  return (void*)status;
  //pthread_exit((void*)status);
}

int main(int argc, char **argv)
{
    printf("I am the main thread with pthreadself %lu, getpid %d, gettid %lu \n",
        pthread_self(), getpid(), syscall(SYS_gettid));
    /*
     * pthreadself是用户态上模拟线程的id, getpid是内核进程,gettid是内核线程
     */
    cout << "original x: " << Thread::x << endl;  //static member has been stablished during compilation
    MyThread1 thd1;
    MyThread2 thd2;

    thd1.start();
    thd2.start();
    /*
     * 以阻塞的方式等待指定的线程(必须是joinable的)结束
     * (thread1里面要执行的函数结束了,调用它的线程thd1也就结束了;或者线程内部通过函数pthread_exit来实现)
     * pthread_join返回时,被等待线程的资源被收回; 如果线程已经结束,那么pthread_join会立即返回。
     */
    thd1.stop();
    printf("thread1 recycled \n");

    /*
     * 线程thd2已经结束,那么pthread_join会立即返回
     */
    thd2.stop();
    printf("thread2 recycled \n");
    return 0;
}

Attach cmake

cmake_minimum_required(VERSION 3.13)
project(untitled)

set(CMAKE_CXX_STANDARD 11)

add_executable(untitled main.cpp)
target_link_libraries(untitled pthread)

运行结果:
I am the main thread with pthreadself 140451626616640, getpid 30689, gettid 30689
original x: 0
create a new thread: with pthreadself 140451609147136, getpid 30689, gettid 30690
create a new thread: with pthreadself 140451600754432, getpid 30689, gettid 30691
T1 gets the lock with pthreadself 140451609147136, getpid 30689, gettid 30690
x=0, so T1 starts waiting and releases the lock
T2 gets the lock with pthreadself 140451600754432, getpid 30689, gettid 30691
T2 signals
T2 signaled and then sleeps…
T2 increases x: 1
T2 releases the lock
T2 exits
T1 returns from the waiting by the signal, with code 0, and then gets the lock
x !=0, so T1 can continue to work…
T1 decreases x: 0
T1 releases the lock
waiting the exit of T1
T1 exits
exit code: 111
thread1 recycled
exit code: 222
thread2 recycled
destructing thread2;
destructing base class: Thread;
destructing thread1;
destructing base class: Thread;

Published 31 original articles · won praise 18 · views 6034

Guess you like

Origin blog.csdn.net/weixin_40027284/article/details/87880156