[C++]线程[1]

简介: 线程的创建和使用
菜鸟驿站

1 创建线程

#include <pthread.h>
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
                   void *(*start_routine) (void *), void *arg);
                   
On success, pthread_create() returns 0; on error, it returns an  error  number, and the contents of *thread are undefined.
                   

e.g.

#include <iostream>
#include <stdio.h>
// 必须的头文件
#include <pthread.h>
 
using namespace std;
 
#define NUM_THREADS 5
 
// 线程的运行函数
void* say_hello(void* args)
{
    printf("%s\n", (char *)args);
    return 0;
}
 
int main()
{
    // 定义线程的 id 变量,多个变量使用数组
    pthread_t tids[NUM_THREADS];
    char para_data[128] = "I am a sub thread";
    for(int i = 0; i < NUM_THREADS; ++i)
    {
        //参数依次是:创建的线程id,线程参数,调用的函数,传入的函数参数
        int ret = pthread_create(&tids[i], NULL, say_hello, (void *)para_data);
        if (ret != 0)
        {
           cout << "pthread_create error: error_code=" << ret << endl;
        }
    }
    //等各个线程退出后,进程才结束,否则进程强制结束了,线程可能还没反应过来;
    pthread_exit(NULL);
}
# g++ thread_test.cpp -lpthread

打印结果:

1.1 线程传递单个参数

#include <iostream>
#include <cstdlib> //exit()
#include <pthread.h>

using namespace std;

#define NUM_THREADS     5

void* PrintHello(void* threadid)
{
    // 对传入的参数进行强制类型转换,由无类型指针变为整形数指针,然后再读取
    int tid = *((int*)threadid);
    cout << "Hello Runoob! 线程 ID, " << tid << endl;
    pthread_exit(NULL);
}

int main()
{
    pthread_t threads[NUM_THREADS];
    int para_data[NUM_THREADS];

    for (int i = 0; i < NUM_THREADS; i++) {
        cout << "main() : 创建线程, " << i << endl;
        // 传入的时候必须强制转换为void* 类型,即无类型指针  
        para_data[i] = i;
        int ret = pthread_create(&threads[i], NULL,
            PrintHello, (void*)&(para_data[i]));
        if (ret) {
            cout << "Error:无法创建线程," << ret << endl;
            exit(-1);
        }
    }
    pthread_exit(NULL);
}

打印结果

main() : 创建线程, 0
main() : 创建线程, 1
Hello Runoob! 线程 ID, 0
main() : 创建线程, 2
Hello Runoob! 线程 ID, 1
main() : 创建线程, 3
Hello Runoob! 线程 ID, 2
main() : 创建线程, 4
Hello Runoob! 线程 ID, 3
Hello Runoob! 线程 ID, 4

1.2 线程传递多个参数

通过结构体传递多个传输
创建指针不用初始化, 但是在使用的时候一定要指定某个空间. 否者会出现Segmentation fault (core dumped)

struct thread_data{
	int thread_id;
	char *message;
};
#include <iostream>
#include <cstdlib>
#include <pthread.h>

using namespace std;

#define NUM_THREADS     5

struct thread_data {
    int  thread_id;
    char* message;
};

void* PrintHello(void* threadarg)
{
    struct thread_data* my_data;

    my_data = (struct thread_data*) threadarg;

    cout << "Thread ID : " << my_data->thread_id;
    cout << " Message : " << my_data->message << endl;

    pthread_exit(NULL);
}

int main()
{
    pthread_t threads[NUM_THREADS];
    struct thread_data td[NUM_THREADS];

    for (int i = 0; i < NUM_THREADS; i++) {
        cout << "main() : creating thread, " << i << endl;
        td[i].thread_id = i;
        td[i].message = (char*)"This is message";
        int ret = pthread_create(&threads[i], NULL,
            PrintHello, (void*)&td[i]);
        if (ret) {
            cout << "Error:unable to create thread," << ret << endl;
            exit(-1);
        }
    }
    pthread_exit(NULL);
}

2 等待线程结束

NOTE: pthread_join通过阻塞的方式等待线程结束, 如果没有该函数, 则主线程很快结束从而整个进程结束, 从而使创建的线程没有机会开始执行就结束了.
线程链接和可分离: 创建的线程和进程一样, 也需要被连接以监听其推出状态, 否则也会变成僵尸线程. 退出后, 内核会保留退出状态数据, 直到取走为止. 处于分离状态的线程, 无法被任何线程执行连接获取其状态, 也无法再返回到可连接状态. 通常称呼分离线程守护线程(daemon threads)

int pthread_join(pthread_t thread, void **retval);
On success, pthread_join() returns 0; on error, it returns an error number.
#include <iostream>
#include <cstdlib>
#include <pthread.h>
#include <unistd.h>

using namespace std;

#define NUM_THREADS     5

void* wait(void* t)
{
    int i;
    long tid;

    tid = (long)t;

    sleep(1);
    cout << "Sleeping in thread " << endl;
    cout << "Thread with id : " << tid << "  ...exiting " << endl;
    pthread_exit(NULL);
}

int main()
{
    int rc;
    int i;
    pthread_t threads[NUM_THREADS];
    pthread_attr_t attr;
    void* status;

    // 初始化并设置线程为可连接的(joinable)
    pthread_attr_init(&attr);
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);

    for (i = 0; i < NUM_THREADS; i++) {
        cout << "main() : creating thread, " << i << endl;
        rc = pthread_create(&threads[i], NULL, wait, (void*)&i);
        if (rc) {
            cout << "Error:unable to create thread," << rc << endl;
            exit(-1);
        }
    }

    // 删除属性,并等待其他线程
    pthread_attr_destroy(&attr);
    for (i = 0; i < NUM_THREADS; i++) {
        rc = pthread_join(threads[i], &status);
        if (rc) {
            cout << "Error:unable to join," << rc << endl;
            exit(-1);
        }
        cout << "Main: completed thread id :" << i;
        cout << "  exiting with status :" << status << endl;
    }

    cout << "Main: program exiting." << endl;
    pthread_exit(NULL);
}

3 线程库的使用

NOTE: c++11之后
hardware_concurrency(): 这个函数用于获取程序可以调动的最大线程数,在多核系统中可能代表CPU核数。这个函数返回值仅可以作为参考,因为有可能返回0。

thread t(hello);
t.join();

thread a(hello);
a.detach();

for (int i = 0; i < 5; ++i)
threads[i] = thread(pause_thread, i + 1);
for (auto& thread : threads)
    thread.join();

# g++ thread_test.cpp -std=c++11 -lpthread
#include <iostream>

#include <thread>

using namespace std;

thread::id main_thread_id = this_thread::get_id();

void hello()
{
    cout << "Hello Concurrent World\n";
    if (main_thread_id == this_thread::get_id())
        cout << "This is the main thread.\n";
    else
        cout << "This is not the main thread.\n";
}

void pause_thread(int n) {
    this_thread::sleep_for(chrono::seconds(n));
    cout << "pause of " << n << " seconds ended\n";
}

int main() {
    thread t(hello);
    cout << "data: "<<t.hardware_concurrency() << endl;//可以并发执行多少个(不准确)
    //cout << "native_handle " << t.native_handle() << endl;//可以并发执行多少个(不准确)
    t.join();
    thread a(hello);
    a.detach();
    thread threads[5];                         // 默认构造线程

    cout << "Spawning 5 threads...\n";
    for (int i = 0; i < 5; ++i)
        threads[i] = thread(pause_thread, i + 1);   // move-assign threads
    cout << "Done spawning threads. Now waiting for them to join:\n";
    for (auto& thread : threads)
        thread.join();
    cout << "All threads joined!\n";
}

在这里插入图片描述
技术交流QQ群:916932330(如有疑问或者技术问题请加群)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值