C++的并发、轮询以及多线程机制(thread以及pthread)

在了解多线程之前我们首先需要了解并发的机制

并发:多个任务同时间段进行,一个可执行exe文件就是一个进程,并发的实现可通过执行多个exe文件或者给它开多线程。

轮询:单核cpu不能实现真正的并发,10个任务,第一个任务执行10ms,马上切换到第二个任务,看着就像多任务同时处理并发,但是是个假并发。这种方法也叫轮询

如果你cpu4核的,执行3线程任务,那就可以做到并发,5个任务就还是需要通过轮询,所以线程并不是越多越好。轮询会浪费CPU性能在切换上。
查询cpu核心数的代码如下:
还是国际惯例,先复制代码编译一下更容易理解。

    int count = std::thread::hardware_concurrency();
    printf("此电脑核心数为:%d\n" , count);

thread例子如下:

join:跟主线程汇合,等线程执行完毕再执行进程,这个就是阻塞
可以看以下代码例子:

// An highlighted block
#include<iostream>
#include<thread>

void fuction_1()
{
    std::cout<<"线程开始运行" <<std::endl;
    std::cout<<"Hello World" <<std::endl;
}
int main()
{
    std::cout<<"进程开始" <<std::endl;
    std::thread t1(fuction_1);
    t1.join();  //不加jion,主线程就会继续执行,然后子线程还没结束
    //程序却已经运行结束了,并且销毁了线程
    //t1.detach();
    std::cout<<"进程开始1" <<std::endl;
    std::cout<<"进程准备结束" <<std::endl;
}

不加 t1.join,线程会继续往下走,而不管子线程

detach:分离,和主线程各走各的,但如果你先detach再join,则会报错,join方法要加个判断if(t1.joinable()),二者选一个,不然会跟主线程产生混乱冲突等

// An highlighted block
    t1.detach();
    if(t1.joinable())
    {
        t1.join();
    }

detach执行后,子现场会驻留到后台运行,所以叫守护线程。
一个线程只能被deatch或join一次,可以根据实际使用需求来决定使用哪一种方法。
要注意,线程只能被move,不能被赋值,如下:move完之后,t1为空

std::thread t2=std::move(t1);

上面的是thread函数是C++11自带的一个线程函数的机制,他本源也是对pthread的一个封装,我们看原生的pthread函数如何使用:(如果输入man 2 pthread_create提示没有函数的话,需先执行下面的操作)
注意,如果你的系统更换过镜像源,则需要先把/etc/apt目录下的sources.list文件内容换回官方的源,然后执行sudo apt-get update,之后还是可能会报错,按照提示运行这句sudo apt-get -f install,最后才安装关于线程的man提示手册sudo apt-get install manpages-posix manpages-posix-dev然后你输入man 2 pthread_create才能看到函数原型
头文件
  #include<pthread.h>
我们先来看创建线程的函数原型pthread_create
函数声明

int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
    void *(*start_routine) (void *), void *arg);
    
 Compile and link with -pthread.

里面一共有四个参数
线程pthread函数
第一个是传出参数,当创建成功会传出新创建的线程id
第二个是只读的,描述的是线程的属性,通过调整线程属性可以调整线程分离或其他,也可以不传,写NULL即可
第三个是回调函数,返回值是void*,参数也是void*
第四个参数就是第三个参数的void*
下面那行提示就是编译的时候需手动链接线程库-pthread
下面一起写一个最简单的线程函数来加深印象。

#include<pthread.h>
#include<iostream>
#include<unistd.h>
using namespace std;
void* xiancheng(void *)
{
    cout<<"i am a xiancheng"<<endl;
    return NULL;
}
int main()
{
    pthread_t tid;
    cout<<"i am main"<<endl;
    pthread_create(&tid,NULL,xiancheng,NULL);
    sleep(1);
    return 0;
}

在这里插入图片描述
加个sleep是让主线程等待子线程,当然正规的其实应该使用pthread_join函数。
我们刚才可以看到线程是可以传参的,那么这个void*类型的怎么传呢?直接把int型强转成void *吗?字节数不一样会导致数据丢失或其他问题,所以我们传指针就好

#include<pthread.h>
#include<iostream>
#include<unistd.h>
using namespace std;
void* xiancheng(void *arg)
{
    int  ax=(*(int*)arg);
    cout<<"i am a xiancheng  "<<ax<<endl;
    return NULL;
}
int main()
{
    pthread_t tid;
    cout<<"i am main"<<endl;
    int args=520;
    pthread_create(&tid,NULL,xiancheng,(void*)&args);
    pthread_join(tid,NULL);
    return 0;
}
  • 3
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值