#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;