C++线程

发布时间 2023-11-17 21:03:18作者: 长弓令山

进程以CPU为运行单位,多个CPU可以实现进程并行,单个CPU可以实现进程并发(进程调度)

线程以CPU的核心为运行单位,多个CPU内核可以实现线程并行,单个内核可以实现线程并发(线程调度)

1、创建和结束一个线程 

#include <iostream>
#include <pthread.h>
/// @brief 创建一个线程
/// @param  线程标识符指针
/// @param  线程属性对象
/// @param  线程运行函数指针
/// @param  线程运行函数参数
/// @return 创建线程成功时,函数返回 0,若返回值不为 0 则说明创建线程失败。
// int pthread_create(pthread_t *, const pthread_attr_t *, void *(__PTW32_CDECL *)(void *), void *);



// 线程运行函数
void *pthreadFun(void *arg)
{
    cout << "num is " << *(int *)arg << endl;
    // 终止线程
    pthread_exit(nullptr);
}

int main(int argc, char **argv)
{
    // 线程标识符
    pthread_t tid[5] = {0};
    for (int i = 0; i < THREAD_NUM; i++) 
  { pthread_create(
&tid[i], nullptr, pthreadFun, (void *)&i); // 等待线程启动 sleep(1); } return 0; }

 2、连接和分离线程 

连接线程:将子线程连接入主线程,主线程阻塞等待子线程运行结束。然后回收子线程资源。

#include <csignal>
#include <cstdlib>
#include <iostream>
#include <pthread.h>
#include <unistd.h>

using namespace std;

#define THREAD_NUM 5
void signalHander(int sigNum) { cout << "signum :" << signal << endl; }

/// @brief 创建一个线程
/// @param  线程标识符指针
/// @param  线程属性对象
/// @param  线程运行函数指针
/// @param  线程运行函数参数
/// @return 创建线程成功时,函数返回 0,若返回值不为 0 则说明创建线程失败。
// int pthread_create(pthread_t *, const pthread_attr_t *, void *(__PTW32_CDECL *)(void *), void *);

// pthread_attr_init(pthread_attr_t *);

/// @brief 初始化线程属性组
/// @param 线程标识符
pthread_attr_destroy(pthread_attr_t *);

/// @brief 连接线程,将主线程合入子线程,主线程等待子线程结束然后再向下执行
/// @param 线程标识符
/// @param 子线程返回值
pthread_join(pthread_t, void **);

/// @brief 分离线程
/// @param 线程标识符
pthread_detach(pthread_t);

// 线程运行函数
void *pthreadFun(void *arg)
{

    cout << "num is " << *(int *)arg << endl;
    // 终止线程
    pthread_exit(nullptr);
}

int main(int argc, char **argv)
{
    // 线程标识符
    pthread_t tid[5] = {0};
    // 线程属性组
    pthread_attr_t pat;
    pthread_attr_init(&pat);
    pthread_attr_setdetachstate(&pat, PTHREAD_CREATE_JOINABLE);
    for (int i = 0; i < 5; i++) {
        pthread_create(&tid[i], &pat, pthreadFun, (void *)&i);
        // 等待一个线程启动再启动下一个线程
        sleep(1);
    }
    void *statRet = nullptr;
    for (int i = 0; i < 5; i++) {
        pthread_join(tid[i], &statRet);
        cout << "statRet :" << statRet << endl;
    }
    pthread_attr_destroy(&pat);

    return 0;
}

 

分离线程:子线程与主线程分离,子线程结束后自动回收资源。

 

/// @brief 创建一个线程
/// @param  线程标识符指针
/// @param  线程属性对象
/// @param  线程运行函数指针
/// @param  线程运行函数参数
/// @return 创建线程成功时,函数返回 0,若返回值不为 0 则说明创建线程失败。
int pthread_create(pthread_t *, const pthread_attr_t *, void *(__PTW32_CDECL *)(void *), void *);

/// @brief 初始化线程属性结构体
/// @param 线程属性结果体指针
pthread_attr_init(pthread_attr_t *);

/// @brief 初始化线程属性组
/// @param 线程标识符
pthread_attr_destroy(pthread_attr_t *);

/// @brief 连接线程,将主线程合入子线程,主线程等待子线程结束然后再向下执行
/// @param 线程标识符
/// @param 子线程返回值
pthread_join(pthread_t, void **);

/// @brief 分离线程
/// @param 线程标识符
pthread_detach(pthread_t);

// 线程运行函数
void *pthreadFun(void *arg)
{

    cout << "num is " << *(int *)arg << endl;
    // 终止线程
    pthread_exit(nullptr);
}

int main(int argc, char **argv)
{
    // 线程标识符
    pthread_t tid[5] = {0};
    // 线程属性组
    pthread_attr_t pat;
    pthread_attr_init(&pat);
    pthread_attr_setdetachstate(&pat, PTHREAD_CREATE_DETACHED);
for (int i = 0; i < 5; i++) {
        pthread_create(&tid[i], &pat, pthreadFun, (void *)&i);
        // 等待一个线程启动再启动下一个线程
        sleep(1);
    }
    void *statRet = nullptr;
    for (int i = 0; i < 5; i++) {
        pthread_detach(tid[i]);
        cout << "statRet :" << statRet << endl;
    }
    pthread_attr_destroy(&pat);

    return 0;
}

3、线程间的信号量

(信号是不同于信号量的吧哈哈哈哈哈,刚开始把信号当成信号量调了好半天程序,蠢死我了)

#include <iostream>
#include <pthread.h>
#include <semaphore.h>
using namespace std;

/// @brief 初始化未命名一个信号量
/// @param sem 一个信号量的指针
/// @param pshared 标志信号量是进程共享还是线程共享,为0则是线程间共享,不为0则是进程间共享
/// @param value 设置信号量的初始值
/// @return 成功返回0,失败返回-1
int sem_init(sem_t *sem, int pshared, unsigned int value);

/// @brief 销毁一个未命名信号量
/// @param sem 一个信号量的指针
/// @return 成功返回0,失败返回-1
int sem_destroy(sem_t *sem);

/// @brief 锁定、递减信号量
/// @param sem 要锁定的信号量的指针
/// @return 成功返回0,失败返回-1
int sem_wait(sem_t *sem);

/// @brief 解锁信号量
/// @param sem 要解锁的信号量的指针
/// @return 成功返回0,失败返回-1
int sem_post(sem_t *sem);

void *pthread_1(void *arg);
void *pthread_2(void *arg);

sem_t sem1;
sem_t sem2;
int main(int argc, char **argv)
{
    int ret = 0;
    if (0 != sem_init(&sem1, 0, 1))
        cerr << "sem_init" << endl;
    if (0 != sem_init(&sem2, 0, 1))
        cerr << "sem_init" << endl;
    pthread_t tid[2] = {0};
    pthread_attr_t pat_1;
    pthread_attr_t pat_2;
    pthread_attr_init(&pat_1);
    pthread_attr_setdetachstate(&pat_1, PTHREAD_CREATE_JOINABLE);
    pthread_attr_init(&pat_2);
    pthread_attr_setdetachstate(&pat_2, PTHREAD_CREATE_JOINABLE);

    pthread_create(&tid[0], &pat_1, pthread_1, nullptr);
    pthread_create(&tid[1], &pat_2, pthread_2, nullptr);
    void *statRet = nullptr;
    pthread_join(tid[0], &statRet);
    pthread_join(tid[1], &statRet);

    pthread_attr_destroy(&pat_1);
    pthread_attr_destroy(&pat_2);
    pthread_exit(nullptr);

    if (ret != sem_destroy(&sem1))
        cerr << "sem1_destroy" << endl;
    if (ret != sem_destroy(&sem2))
        cerr << "sem2_destroy" << endl;
    return 0;
}

void *pthread_1(void *arg)
{
    while (1) {
        if (0 != sem_wait(&sem1))
            cerr << "sem1_wait" << endl;
        cout << "wait sem1 OK" << endl;
        sleep(1);
        if (0 != sem_post(&sem2))
            cerr << "sem2_post" << endl;
        cout << "post sem2 OK" << endl;
        sleep(1);
    }
    pthread_exit(nullptr);
}

void *pthread_2(void *arg)
{
    while (1) {
        if (0 != sem_wait(&sem2))
            cerr << "sem2_wait" << endl;
        cout << "wait sem2 OK" << endl;
        sleep(1);
        if (0 != sem_post(&sem1))
            cerr << "sem1_post" << endl;
        cout << "post sem1 OK" << endl;
        sleep(1);
    }
    pthread_exit(nullptr);
}