std::thread && pthread_create && std::chrono时间库及应用

C++ std::thread join()的理解

https://www.cnblogs.com/adorkable/p/12722209.html

总结理解一下就是两个关键点:

谁调用了这个函数?

调用了这个函数的线程对象,一定要等这个线程对象的方法(在构造时传入的方法)执行完毕后(或者理解为这个线程的活干完了!),这个join()函数才能得到返回。

在什么线程环境下调用了这个函数?

必须要等线程方法执行完毕后才能返回,那必然是阻塞调用线程的,也就是说如果一个线程对象在一个线程环境调用了这个函数,那么这个线程环境就会被阻塞,直到这个线程对象在构造时传入的方法执行完毕后,才能继续往下走,另外如果线程对象在调用join()函数之前,就已经做完了自己的事情(在构造时传入的方法执行完毕),那么这个函数不会阻塞线程环境,线程环境正常执行。

C++11 std::thread detach()与join()用法总结

两者区别

在声明一个std::thread对象之后,都可以使用detach和join函数来启动被调线程, 区别在于两者是否阻塞主调线程。

(1)当使用join()函数时,主调线程阻塞,等待被调线程终止,然后主调线程回收被调线程资源,并继续运行;

(2)当使用detach()函数时,主调线程继续运行,被调线程驻留后台运行,主调线程无法再取得该被调线程的控制权。当主调线程结束时,由运行时库负责清理与被调线程相关的资源。

detach()

detach调用之后,目标线程就成为了守护线程,驻留后台运行,与之关联的std::thread对象失去对目标线程的关联,无法再通过std::thread对象取得该线程的控制权。当线程主函数执行完之后,线程就结束了,运行时库负责清理与该线程相关的资源。

当一个thread对象到达生命期终点而关联线程还没有结束时,则thread对象取消与线程之间的关联,目标线程线程则变为分离线程继续运行。

当调用join函数时,调用线程阻塞等待目标线程终止,然后回收目标线程的资源。

detach是使主线程不用等待子线程可以继续往下执行,但即使主线程终止了,子线程也不一定终止。

#include <iostream>
#include <chrono>
#include <thread>
 
void independentThread() 
{
    std::cout << "Starting concurrent thread.\n";
    std::this_thread::sleep_for(std::chrono::seconds(2));
    std::cout << "Exiting concurrent thread.\n";
}
 
void threadCaller() 
{
    std::cout << "Starting thread caller.\n";
    std::thread t(independentThread);
    t.detach();
    //t.join();
    std::this_thread::sleep_for(std::chrono::seconds(1));
    std::cout << "Exiting thread caller.\n"; 
}
int main() 
{
    threadCaller();
    std::this_thread::sleep_for(std::chrono::seconds(5));

}

get_id: 获取线程 ID。

yield: 当前线程放弃执行,操作系统调度另一线程继续执行。

sleep_until: 线程休眠至某个指定的时刻(time point),该线程才被重新唤醒。

sleep_for: 线程休眠某个指定的时间片(time span),该线程才被重新唤醒,不过由于线程调度等原因,实际休眠时间可能比
sleep_duration 所表示的时间片更长。

get_id()
    std::thread t(independentThread);
    std::thread::id t1_id = t.get_id();
    std::cout << t1_id <<".\n";
   输出:140686121973504.
hardware_concurrency并发数

返回实现支持的并发线程数。应该只把该值当做提示。

#include <iostream>
#include <thread>
 
int main() {	
    unsigned int n = std::thread::hardware_concurrency();
    std::cout << n << " concurrent threads are supported.\n";
}
输出:4 concurrent threads are supported.

pthread_create函数

linux下用C语言开发多线程程序,Linux系统下的多线程遵循POSIX线程接口,称为pthread。

int  pthread_create(pthread_t *tidp, const  pthread_attr_t *attr,( void *)(*start_rtn)( void *), void  *arg);

参数
  第一个参数为指向线程标识符的指针。
  第二个参数用来设置线程属性。
  第三个参数是线程运行函数的起始地址。
  最后一个参数是运行函数的参数。
  另外,在编译时注意加上-lpthread参数,以调用静态链接库。因为pthread并非Linux系统的默认库

#include <pthread.h>
#include <queue>
#include <stdio.h>
#include <unistd.h>
 
// 注意pthread_*函数返回的异常值
 
pthread_mutex_t mutex;
pthread_cond_t condvar;
 
std::queue<int> msgQueue;
struct Produce_range {
    int start;
    int end;
};
 
void *producer(void *args)
{
    int start = static_cast<Produce_range *>(args)->start;
    int end = static_cast<Produce_range *>(args)->end;
    for (int x = start; x < end; x++) {
        usleep(200 * 1000);
        pthread_mutex_lock(&mutex);
        msgQueue.push(x);
        pthread_mutex_unlock(&mutex);
        pthread_cond_signal(&condvar);
        printf("Produce message %d\n", x);
    }
    pthread_exit((void *)0);
    return NULL;
}
 
void *consumer(void *args)
{
    int demand = *static_cast<int *>(args);
    while (true) {
        pthread_mutex_lock(&mutex);
        while (msgQueue.size() <= 0) {
            pthread_cond_wait(&condvar, &mutex);
        }
        if (msgQueue.size() > 0) {
            printf("Consume message %d\n", msgQueue.front());
            msgQueue.pop();
            --demand;
        }
        pthread_mutex_unlock(&mutex);
        if (!demand) break;
    }
    pthread_exit((void *)0);
    return NULL;
}
 
 
int main()
{
    pthread_attr_t attr;
    pthread_attr_init(&attr);
    pthread_mutex_init(&mutex, NULL);
    pthread_cond_init(&condvar, NULL);
 
    pthread_t producer1, producer2, producer3, consumer1, consumer2;
 
    Produce_range range1 = {0, 10};
    pthread_create(&producer1, &attr, producer, static_cast<void *>(&range1));
    Produce_range range2 = {range1.end, range1.end + 10};
    pthread_create(&producer2, &attr, producer, static_cast<void *>(&range2));
    Produce_range range3 = {range2.end, range2.end + 10};
    pthread_create(&producer3, &attr, producer, static_cast<void *>(&range3));
 
    int consume_demand1 = 20;
    int consume_demand2 = 10;
    pthread_create(&consumer1, &attr, consumer, 
            static_cast<void *>(&consume_demand1));
    pthread_create(&consumer2, &attr, consumer, 
            static_cast<void *>(&consume_demand2));
 
    pthread_join(producer1, NULL);
    pthread_join(producer2, NULL);
    pthread_join(producer3, NULL);
    pthread_join(consumer1, NULL);
    pthread_join(consumer2, NULL);
} 

std::chrono时间库及应用

(1)chrono命名空间定义好的时间单位
   typedef duration <Rep, ratio<3600,1>> hours;
   typedef duration <Rep, ratio<60,1>> minutes;
   typedef duration <Rep, ratio<1,1>> seconds;
   typedef duration <Rep, ratio<1,1000>> milliseconds;
   typedef duration <Rep, ratio<1,1000000>> microseconds;
   typedef duration <Rep, ratio<1,1000000000>> nanoseconds;

使用举例:


chrono::minutes mintu{2};//2分钟
chrono::seconds sec{3};//3秒钟
chrono::milliseconds mills{500};//500毫秒
auto dul = sec - mills;//两者差值,单位默认转到更小的 2500ms
dul.count(); //值为2500
std::this_thread::sleep_for(std::chrono::milliseconds(100)); //当前线程休眠100毫秒
//chrono::duration_cast<>() 时间单位转换
chrono::duration_cast<chrono::seconds>(mintu).count(); //2分钟换算为120秒 
(2) 获取当前时间(time_point 表示一个时间点)
获取当前时间
 
chrono::system_clock::time_point now = chrono::system_clock::now();//当前时间time_point格式
std::time_t oldTime = time(nullptr);//c函数获取当前时间
cout << "oldTime = " << oldTime << endl;
chrono::system_clock::time_point timePoint = chrono::system_clock::now();//stl库获取当前时间
std::time_t newTime = chrono::system_clock::to_time_t(timePoint);//转换为旧式接口,单位:秒
cout<<"newTime = " << newTime <<endl;// oldTime == timeT
格式化打印当前时间
 
/*  chrono::system_clock::time_point与std::time_t类型可相互函数
 *  chrono::system_clock::to_time_t()   
 *  chrono::system_clock::from_time_t()     
 */
std::time_t nowTime = chrono::system_clock::to_time_t(now);//转换为 std::time_t 格式 
std::put_time(std::localtime(&nowTime), "%Y-%m-%d %X"); // 2019-06-18 14:25:56
 
// !std::localtime非线程安全,使用localtime_r函数代替
struct tm cutTm = {0};
std::put_time(localtime_r(&nowTime, &cutTm), "%Y-%m-%d %X");// 2019-06-18 14:25:56
(3)打印程序耗时
/*1、打印耗时,取变量构造函数与析构函数的时间差,单位ms*/
class SpendTime
{
public:
    SpendTime():_curTimePoint(std::chrono::steady_clock::now())
    {
    }
    
    ~SpendTime()
   {
        auto curTime = std::chrono::steady_clock::now();
        auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(curTime - 
                        _curTimePoint);
        cout<<"SpendTime = "<<  duration.count() <<"ms"<<endl;
   }
 
private:
    std::chrono::steady_clock::time_point _curTimePoint;
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值