C++11常用特性(下-并发与并行)

首先谈谈对并发和并行的理解 并发:在操作系统中,是指一个时间段中有几个程序都处于已启动运行到运行完毕之间,且这几个程序都是在同一个处理机上运行,但任一个时刻点上只有一个程序在处理机上运行。 并行:在操作系统中是指,一组程序按独立异步的速度执行,无论从微观还是宏观,程序都是一起执行的。 因此并发和并行的区别就是,是否真正同时执行,并发是在一个时间段内几个任务都运行完毕,宏观上是一起执行,微观上顺序执行。并行是真正的多个任务同时执行。 互联网所说的高并发,也就是希望充分的利用CPU/内存等系统资源,让CPU尽可能不闲着

一、thread

#include <iostream>
#include <thread>
#include <unistd.h>
#include <error.h>
#define NUM_THREADS 10
using namespace std;

//void work(int& arg) {
void work(int arg) {
    std::cout << "this is " << arg << std::endl;
};

int main()
{
    thread threads[NUM_THREADS];
    for(int i = 0; i < NUM_THREADS; ++i){
        //threads[i] = std::thread(work, std::ref(i));
        threads[i] = std::thread(work, i);
    }

    for(int i=0; i < NUM_THREADS; ++i ){
        threads[i].join();
    }

    return 0;
}
C++11新增了thread类,用法如上图,如果函数的参数是引用的话,实参需要添加std::ref() 注意:thread的类,不能设置线程某些属性,因此在项目中还是使用老版本的多线程函数

二、mutex

提供了lock_guard和unique_lock两种
#include <iostream>
#include <thread>
#include <unistd.h>
#include <error.h>
#include <mutex>
#define NUM_THREADS 10
using namespace std;
std::mutex mtx;

//10个线程
void work(int& arg) {
    std::lock_guard<std::mutex> lock(mtx);
    arg++;
};

int main()
{
    int rc = 0;
    int sum = 0;

    thread threads[NUM_THREADS];

    for(int i = 0; i < NUM_THREADS; ++i){
        threads[i] = std::thread(work, std::ref(sum));
        if (rc) {
            return 1;
        }
    }

    for(int i=0; i < NUM_THREADS; ++i ){
        threads[i].join();
    }
    std::cout << "sum:" << sum << std::endl;

    return 0;
}
#include <iostream>
#include <thread>
#include <unistd.h>
#include <error.h>
#include <mutex>
#define NUM_THREADS 10
using namespace std;
std::mutex mtx;

//10个线程
void work(int& arg) {
    std::unique_lock<std::mutex> uni_lock(mtx); // 注意: 构造函数之后,就默认是lock的状态
    arg++;
    uni_lock.unlock();
};

int main()
{
    int rc = 0;
    int sum = 0;

    thread threads[NUM_THREADS];

    for(int i = 0; i < NUM_THREADS; ++i){
        threads[i] = std::thread(work, std::ref(sum));
        if (rc) {
            return 1;
        }
    }

    for(int i=0; i < NUM_THREADS; ++i ){
        threads[i].join();
    }
    std::cout << "sum:" << sum << std::endl;

    return 0;
}
lock_guard 不允许手动unlock/lock,性能消耗小,创建即加锁,作用域结束自动析构并解锁,无需手工解锁,不能中途解锁,必须等作用域结束才解锁,不能复制 unique_lock更加灵活,允许手动多次 unlock/lock 性能消耗大,默认是加锁状态 在实际项目当中,可以把要加锁的部分,单独做一个函数,用lock_guard,出了作用域自动解锁,控制了锁的粒度,性能最好

三、condition

注意:该条件变量只能搭配std::mutex或者std::unique_lock,无法使用lock_guard
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <condition_variable>
#define CUSTOMER_COUNT 2
#define PRODUCTER_COUNT 1
int g_num = 0;
std::condition_variable cv;
std::mutex mtx;
void* customer(void* arg)//消费者线程
{
    int inum = 0;
    inum = *(int *)arg;
    while (1)
    {
        std::unique_lock<std::mutex> lock(mtx);
        while (g_num == 0)
        {
            printf("\nwaiting start\n");
            cv.wait(lock);//阻塞等待唤醒
            printf("waiting end\n");
        }
        g_num--;//消费产品
    }
    pthread_exit(0);
}

void* producter(void* arg)//生产者线程
{
    int inum = 0;
    inum = *(int *)arg;
    while (1)
    {
        std::unique_lock<std::mutex> lock(mtx);
        printf("The num of g_num:%d\n", g_num);
        g_num++;//生产产品
        cv.notify_all(); //通知消费者
    }
    pthread_exit(0);
}

int main()
{
    int i = 0;
    pthread_t threadArray[CUSTOMER_COUNT + PRODUCTER_COUNT + 10];//线程数组

    for (i = 0; i < PRODUCTER_COUNT; i++)//创建生产者线程
    {
        pthread_create(&threadArray[i], NULL, producter, (void*)&i);
    }

    for (i = 0; i < CUSTOMER_COUNT; i++)//创建消费者线程
    {
        pthread_create(&threadArray[i + CUSTOMER_COUNT], NULL, customer, (void*)&i);
    }

    for (i = 0; i < PRODUCTER_COUNT + CUSTOMER_COUNT; i++)//等待线程结束
    {
        pthread_join(threadArray[i], NULL);
    }

    return 0;
}
原理都是一致,生产者通知,消费者实时等待唤醒去消费
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值