一、最开始的代码

主函数,等待按下q退出,线程g_thread,一直打印信息,但是现在就是不能正常退出!

#include <pthread.h>
#include <stdbool.h>
#include <stdio.h>
#include <unistd.h>
#include <unistd.h>


int main() {
  InitFun();
  do {
    printf("%s %d  ----press q key to exit!--- \n", __func__, __LINE__);
    usleep(100 * 1000);
  } while (getchar() != 'q');
  UnInitFun();
  return 0;
}


pthread_t g_thread;

void* testFun(void* arg) {
  while (1) {
    usleep(300 * 1000);
    printf("%s %d =================\n", __func__, __LINE__);
  }

  return NULL;
}

int InitFun() {

  if (pthread_create(&g_thread, NULL, testFun, NULL) != 0) {
    printf("%s %d Handle thread creation error", __func__, __LINE__);
    return -1;
  }

  return 0;
}
int UnInitFun() {
  if (pthread_join(g_thread, NULL) != 0) {
    printf("%s %d Handle thread join error", __func__, __LINE__);
    return -1;
  }
  return 0;
}

修改方案一

添加一个全局变量g_exitFlag

#include <pthread.h>
#include <stdbool.h>
#include <stdio.h>
#include <unistd.h>
#include <unistd.h>

int main() {
  InitFun();
  do {
    printf("%s %d  ----press q key to exit!--- \n", __func__, __LINE__);
    usleep(100 * 1000);
  } while (getchar() != 'q');
  UnInitFun();
  return 0;
}
pthread_t g_thread;
int g_exitFlag = 0; 
void* testFun(void* arg) {
  while (!g_exitFlag) {
    usleep(300 * 1000);
    printf("%s %d =================\n", __func__, __LINE__);
  }

  return NULL;
}

int InitFun() {

  if (pthread_create(&g_thread, NULL, testFun, NULL) != 0) {
    printf("%s %d Handle thread creation error", __func__, __LINE__);
    return -1;
  }

  return 0;
}


int UnInitFun() {
    g_exitFlag = 1;
  if (pthread_join(g_thread, NULL) != 0) {
    printf("%s %d Handle thread join error", __func__, __LINE__);
    return -1;
  }
  return 0;
}

修改方案二

使用pthread_cancel,请求取消线程


#include <pthread.h>
#include <stdbool.h>
#include <stdio.h>
#include <unistd.h>
#include <unistd.h>

int main() {
  InitFun();
  do {
    printf("%s %d  ----press q key to exit!--- \n", __func__, __LINE__);
    usleep(100 * 1000);
  } while (getchar() != 'q');
  UnInitFun();
  return 0;
}


void* testFun(void* arg) {
  while (1) {
    usleep(300 * 1000);
    printf("%s %d =================\n", __func__, __LINE__);
  }

  return NULL;
}

int InitFun() {
  if (pthread_create(&g_thread, NULL, testFun, NULL) != 0) {
    printf("%s %d Handle thread creation error", __func__, __LINE__);
    return -1;
  }

  return 0;
}
int UnInitFun() {
  if (pthread_cancel(g_thread) != 0) {
    printf("%s %d Handle thread cancellation error", __func__, __LINE__);
    return -1;
  }
  if (pthread_join(g_thread, NULL) != 0) {
    printf("%s %d Handle thread join error", __func__, __LINE__);
    return -1;
  }
  return 0;
}

需要注意的是,被取消的线程需要响应取消请求。它可以通过设置取消状态来指定取消的处理方式。线程可以选择忽略取消请求,允许取消,或者在接收到取消请求时执行特定的清理操作

修改方案三

使用pthread_attr_setdetachstate ,让线程处于分离状态,

#include <pthread.h>
#include <stdbool.h>
#include <stdio.h>
#include <unistd.h>
#include <unistd.h>


int main() {
  InitFun();
  do {
    printf("%s %d  ----press q key to exit!--- \n", __func__, __LINE__);
    usleep(100 * 1000);
  } while (getchar() != 'q');

  return 0;
}

pthread_t g_thread;

void* testFun(void* arg) {
    while (1) {
        usleep(300 * 1000);
        printf("%s %d =================\n", __func__, __LINE__);
    }

    return NULL;
}

int InitFun() {
    pthread_attr_t attr;
    pthread_attr_init(&attr);
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);

    if (pthread_create(&g_thread, &attr, testFun, NULL) != 0) {
        printf("%s %d Handle thread creation error", __func__, __LINE__);
        return -1;
    }

    pthread_attr_destroy(&attr);
    return 0;
}

线程 g_thread 被设置为分离状态,无需通过 pthread_join 来等待它结束。主线程可以继续执行其他工作,而 g_thread 在后台运行。主线程在执行完毕后,整个程序就会退出,而不管 g_thread 是否仍在运行。

修改方案四

#include <pthread.h>
#include <stdbool.h>
#include <stdio.h>
#include <unistd.h>
#include <unistd.h>

int main() {
  InitFun();
  do {
    printf("%s %d  ----press q key to exit!--- \n", __func__, __LINE__);
    usleep(100 * 1000);
  } while (getchar() != 'q');
  UnInitFun();
  return 0;
}

pthread_t g_thread;//定义一个线程标识符,用于标识创建的线程
pthread_mutex_t g_mutex;//定义一个互斥锁,用于保护共享资源的访问,确保在同一时刻只有一个线程可以访问这些资源。
pthread_cond_t g_condition;//定义一个条件变量,用于线程之间的同步,允许一个线程等待另一个线程满足某个条件。
volatile bool g_exit_thread = false;//定义一个volatile修饰的布尔变量,用于标识线程是否应该退出。volatile关键字告诉编译器不要对这个变量进行优化,每次访问都应该从内存中读取最新值。

void* testFun(void* arg) {
  while (1) {
    pthread_mutex_lock(&g_mutex);//获取互斥锁,确保只有一个线程能够执行下面的临界区代码。
    if (g_exit_thread) {
      pthread_mutex_unlock(&g_mutex);
      break;
    }
    pthread_mutex_unlock(&g_mutex);//释放互斥锁。

    printf("%s %d =================\n", __func__, __LINE__);
    usleep(500 * 1000);
  }
  pthread_exit(NULL);//在线程退出前调用,通知系统线程已经完成执行。
  return NULL;
}

int InitFun() {
  pthread_attr_t attr;//定义线程属性对象。
  pthread_attr_init(&attr);//初始化线程属性。
  pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);//设置线程属性,使得线程可被其他线程等待并回收资源。

  pthread_mutex_init(&g_mutex, NULL);//初始化互斥锁。
  pthread_cond_init(&g_condition, NULL);//初始化条件变量。

  if (pthread_create(&g_thread, &attr, testFun, NULL) != 0) {
    printf("%s %d Handle thread creation error!", __func__, __LINE__);
    return -1;
  }

  pthread_attr_destroy(&attr);//销毁线程属性。
  return 0;
}

int UnInitFun() {
  pthread_mutex_lock(&g_mutex);//获取互斥锁。
  g_exit_thread = true;//设置退出标志为 true。
  pthread_mutex_unlock(&g_mutex);//释放互斥锁。

  pthread_cond_signal(
      &g_condition);  // 发送条件信号,唤醒线程。

  if (pthread_join(g_thread, NULL) != 0) {//等待线程退出。
    printf("%s %d Handle thread join error!", __func__, __LINE__);
    return -1;
  }

  pthread_mutex_destroy(&g_mutex);//销毁互斥锁。
  pthread_cond_destroy(&g_condition);//销毁条件变量。
  return 0;
}