zoukankan      html  css  js  c++  java
  • C++多线程

    多线是多任务处理的一种特殊方式,多任务处理允许让电脑同事运行两个或两个以上的程序,一般情况下,两种类型的多任务处理:基于进程和基于线程。

    基于进程的多任务处理是程序的并发执行。

    基于线程的多任务处理是同一程序的片段的并发执行。

    多线程程序包含可以同时运行的两个或多个部分。这样的程序中的每个部分称为一个线程,每个线程定义了一个单独的执行路径。

    创建线程:

    下面的程序,可以用来创建一个POSIX线程:

    #include<pthread.h>
    pthread_create(thread,attr,start_routine,arg);

    在这里pthread_create创建一个新的线程,并让它可执行,下面是关于参数的说明:

    参数

    描述

    thread

    指向线程标识符指针

    attr

    一个不透明的属性对象,可以用来设置线程属性。可以指定线程属性对象,也可以使用默认值NULL

    start_routine

    线程运行函数的起始地址,一旦线程被创建就会被执行

    arg

    运行函数的参数,他必须通过把引用作为指针强制转化成void类型传递。如果没有传递参数,则使用NULL

    创建线程成功,函数返回0,反之,创建失败。

    终止线程:

    #include<pthread.h>

    pthread_exit(status)

    在这里,pthread_exit用于显式地退出一个线程通常情况下,pthread_exit()函数在线程完成工作后无须继续存在时被调用。

    如果mian()是在它所创建地线程结束之前结束,并通过pthread_exit()退出,那么其他线程将继续执行。否则,他们将在main()结束时自动被终止。

    实例:

    /***
    pthread.cpp
    ***/
    #include<iostream>
    #include<pthread.h>
    
    using namespace std;
    
    #define NUM_THREADS 5
    
    void* say_hello(void* args)
    {
        cout << "Hello Runoob" << endl;
        return 0;
    }
    
    int main()
    {
        pthread_t tids[NUM_THREADS];
        for(int i = 0; i < NUM_THREADS; ++i)
        {
            int ret = pthread_create(&tids[i],NULL,say_hello,NULL);
            if(0 != ret)
            {
                cout << "pthread_create error : error_code = " << ret << endl;
            }
        }
    
        pthread_exit(NULL);
    }

    运行结果:

    exbot@ubuntu:~/wangqinghe/C++/20190816$ g++ pthread.cpp -o pthread -lpthread

    exbot@ubuntu:~/wangqinghe/C++/20190816$ ./pthread

    Hello Runoob

    Hello Runoob

    Hello Runoob

    Hello Runoob

    Hello Runoob

    以下简单实例使用pthread_create()函数创建五个函数,并接受传入地参数。每个进程打印一个“Hello Runoob” 的 消息。并输出接受的消息,然后调用pthread_exit()终止线程。

    /***
    create.cpp
    ***/
    #include<iostream>
    #include<pthread.h>
    #include<cstdlib>
    
    using namespace std;
    
    #define NUM_THREADS 5
    
    void* say_hello(void* threadid)
    {
        int tid = *((int*)threadid);
        cout << "Hello Runoob! thread ID " << tid << endl;
        pthread_exit(NULL);
    }
    
    int main()
    {
        pthread_t threads[NUM_THREADS];
        int indexes[NUM_THREADS];
        int rc;
        for(int i = 0; i < NUM_THREADS; ++i)
        {
            cout << "main thread : " << i << endl;
            indexes[i] = i ;
            rc = pthread_create(&threads[i],NULL,say_hello,(void*)&(indexes[i]));
            if(rc)
            {
                cout << "pthread_create error : error_code = " << rc << endl;
                exit(-1);
            }
        }
    
        pthread_exit(NULL);
    }

    运行结果:

    exbot@ubuntu:~/wangqinghe/C++/20190816$ g++ create.cpp -o create -lpthread

    exbot@ubuntu:~/wangqinghe/C++/20190816$ ./create

    main thread : 0

    main thread : 1

    main thread : 2

    main thread : 3

    main thread : 4

    Hello Runoob! thread ID 4

    Hello Runoob! thread ID 3

    Hello Runoob! thread ID 2

    Hello Runoob! thread ID 1

    Hello Runoob! thread ID 0

    向线程传递参数

    该实例演示了如果通过结构体传递多个参数,可以在线程回调中传递任意的数据类型,因为它指向void。

    /***
    param.cpp
    ***/
    #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];
        int rc;
        int i;
    
        for(i = 0; i < NUM_THREADS; i++)
        {
            cout << "main() : create thread ," <<  i << endl;
            td[i].thread_id = i;
            td[i].message = (char*) "This is message";
            rc = pthread_create(&threads[i],NULL,PrintHello,(void*)&td[i]);
            if(rc)
            {
                cout << "Error : unable to create thread," << rc << endl;
                exit(-1);
            }
        }
        pthread_exit(NULL);
    }

    运行结果:

    exbot@ubuntu:~/wangqinghe/C++/20190816$ g++ param.cpp -o param -lpthread

    exbot@ubuntu:~/wangqinghe/C++/20190816$ ./param

    main() : create thread ,0

    main() : create thread ,1

    main() : create thread ,2

    main() : create thread ,3

    main() : create thread ,4

    Thread ID :4 Message : This is message

    Thread ID :3 Message : This is message

    Thread ID :2 Message : This is message

    Thread ID :1 Message : This is message

    Thread ID :0 Message : This is message

    连接和分离线程:

    我们可以使用下面两个函数来链接和分离线程:

    pthread_join (thread,status);
    pthread_detach(threaded);

    pthread_join()子程序阻碍调用程序,直到指定的threadid线程终止为止,当创建一个线程时,他的某个属性会定义它是否是可连接的(jionable)或可分离的(detached)。只有创建时定义为可连接的线程才可以被连接。如果线程创建时被定义为不可分离的,那它永远也不能被连接。

    /***
    detached.cpp
    ***/
    #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;
        
        pthread_t threads[NUM_THREADS];
        pthread_attr_t attr;
        void* status;
    
        pthread_attr_init(&attr);
    
        pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_JOINABLE);
    
        for(int i = 0; i < NUM_THREADS; i++)
        {
            cout << "main() : createing thread, " << i << endl;
            rc = pthread_create(&threads[i],NULL,wait,(void*)&i);
            if(rc)
            {
                cout << "Error : unbale to create thread," << rc << endl;
                exit(-1);
            }
        }
    
        pthread_attr_destroy(&attr);
        for(int 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);
    }

    运行结果:

    exbot@ubuntu:~/wangqinghe/C++/20190816$ g++ detached.cpp -o detached -lpthread

    exbot@ubuntu:~/wangqinghe/C++/20190816$ ./detached

    main() : createing thread, 0

    main() : createing thread, 1

    main() : createing thread, 2

    main() : createing thread, 3

    main() : createing thread, 4

    Sleeping in thread

    Thread with id : 140735242066504 .... exiting

    Sleeping in thread

    Thread with id : 140735242066504 .... exiting

    Sleeping in thread

    Thread with id : 140735242066504 .... exiting

    Sleeping in thread

    Thread with id : 140735242066504 .... exiting

    Sleeping in thread

    Thread with id : 140735242066504 .... exiting

    Main:completed thread id : 0  exiting with status : 0

    Main:completed thread id : 1  exiting with status : 0

    Main:completed thread id : 2  exiting with status : 0

    Main:completed thread id : 3  exiting with status : 0

    Main:completed thread id : 4  exiting with status : 0

    Main : program exiting.

    要注意内存泄露问题。

    如果设置为 PTHREAD_CREATE_JOINABLE,就继续用 pthread_join() 来等待和释放资源,否则会内存泄露。

  • 相关阅读:
    Java 第十一届 蓝桥杯 省模拟赛 梅花桩
    Java 第十一届 蓝桥杯 省模拟赛 梅花桩
    Java 第十一届 蓝桥杯 省模拟赛 梅花桩
    Java 第十一届 蓝桥杯 省模拟赛 元音字母辅音字母的数量
    Java 第十一届 蓝桥杯 省模拟赛 元音字母辅音字母的数量
    Java 第十一届 蓝桥杯 省模拟赛 元音字母辅音字母的数量
    Java 第十一届 蓝桥杯 省模拟赛 最大的元素距离
    Java 第十一届 蓝桥杯 省模拟赛 递增序列
    Java 第十一届 蓝桥杯 省模拟赛 递增序列
    Java 第十一届 蓝桥杯 省模拟赛 最大的元素距离
  • 原文地址:https://www.cnblogs.com/wanghao-boke/p/11365256.html
Copyright © 2011-2022 走看看