首页 > 编程语言 >C++线程

C++线程

时间:2023-11-17 21:12:32浏览次数:38  
标签:int void param 线程 C++ pthread sem

进程以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);
}

 

标签:int,void,param,线程,C++,pthread,sem
From: https://www.cnblogs.com/GREEN-FIEID/p/17835096.html

相关文章

  • C++类与继承
    C++类有三种访问修饰符:public(共有的)、private(私有的)、protected(受保护的)类内各区域成员的访问:1、public类内成员函数、类外、友元函数都可以访问。2、private类内成员函数、友元函数可以访问,private区域成员不能在派生类中访问。3、protected与private不同之......
  • 第十四届蓝桥杯省赛 C++B组 ---- 景区导游
    第十四届蓝桥杯省赛C++B组----景区导游LCA原题连接​ lca同时得到按原来路径走的总时间​ 最后输出时处理跳过某个点的时间​ 预处理用bfs或dfs都可以importjava.io.BufferedReader;importjava.io.InputStreamReader;importjava.util.Arrays;importjava.......
  • C++ 指针学习笔记
    C++指针学习笔记引入指针是什么指针是一个变量,其值为另一个变量的地址。指针声明的一般形式为:type*ptr_name;type是指针的基类型,ptr_name是指针的名称,*用来指定一个变量是指针对于一个指针,需要明确四个方面的内容:指针的类型、指针所指向的类型、指针的值(指针所指向的......
  • C++从零复习
    0.前言子曰:“温故而知新,可以为师矣。”学习了知识,不复习怎么行。这篇随笔是为C++小白写的复习资料,根据目录使用效果更佳。悄悄告诉你:听课的时候走神了也可以查缺补漏哦1.顺序结构(1)框架头文件#include<clude_name>//将名为“clude_name”的头文件导入//常用头文件实例#i......
  • C++ STL String用法
    string在C语言中,提供了字符串的操作,但只能通过字符数组的方式来实现字符串。而string则是一个简单的类,使用简单,在OI竞赛中被广泛使用。相较于其他STL容器,string的常数可以算是非常优秀的,基本与字符数组不相上下。string常用操作输出strings="123";printf("%s......
  • .NET处理线程安全的方法、类和解决方案
    使用锁机制:Monitor类:提供了Enter和Exit方法,可以使用Monitor.Enter(obj)锁定一个对象,使用Monitor.Exit(obj)释放锁。lock关键字:C#中的lock关键字会自动创建一个Monitor锁,确保在同一时间只有一个线程可以进入被lock包裹的代码块。使用互斥体(Mutex):Mutex类:提供了WaitOne......
  • 【C++中cin在Qt输出终端无法手动输入问题解决办法(详细)】
    现象:在Qt中使用cin进行对一个变量z进行输入,然后在用cout对z进行输出,结果没有进行手动输入,程序自动凭空出现类似512,32759等一些数值输出。 解决办法:第一步:在Qt左侧项目栏,在.pro文件中添加一行代码CONFIG+=console 第二步:在项目--运行--勾选在终端中运行(Runinterminal) 配置......
  • JAVA解析Excel文件 + 多线程 + 事务回滚
    1.项目背景:客户插入Excel文件,Ececel文件中包含大量的数据行和数据列,单线程按行读取,耗时大约半小时,体验感不好。思路:先将excel文件按行读取,存入List,然后按照100均分,n=list.szie()/100+1;n就是要开启的线程总数。(实际使用的时候,数据库连接池的数量有限制,n的大小要结合数据库连......
  • JAVA 解析Excel + 多线程 + 事务回滚(2)
    该方法为网上查询,感觉可行,并未真正尝试。主线程:packagecom.swagger.demo.service;importcom.alibaba.excel.context.AnalysisContext;importcom.alibaba.excel.event.AnalysisEventListener;importcom.swagger.demo.config.SpringJobBeanFactory;importcom.swagger.demo.m......
  • 4.2 Windows驱动开发:内核中进程线程与模块
    内核进程线程和模块是操作系统内核中非常重要的概念。它们是操作系统的核心部分,用于管理系统资源和处理系统请求。在驱动安全开发中,理解内核进程线程和模块的概念对于编写安全的内核驱动程序至关重要。内核进程是在操作系统内核中运行的程序。每个进程都有一个唯一的进程标识符(PI......