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

    一、C/C++多线程操作说明

    C/C++多线程基本操作如下: 
    1. 线程的建立结束 
    2. 线程的互斥和同步 
    3. 使用信号量控制线程 
    4. 线程的基本属性配置 

    在C/C++代码编写时,使用多线程机制,首先需要做的事情就是声明引用,具体如下:

    #include "pthread.h"

    二、线程基本操作方法

    基本线程操作:

    1. pthread_create():创建线程开始运行相关线程函数,运行结束则线程退出

    2. pthread_eixt():因为exit()是用来结束进程的,所以则需要使用特定结束线程的函数

    3. pthread_join():挂起当前线程,用于阻塞式地等待线程结束,如果线程已结束则立即返回,0=成功

    4. pthread_cancel():发送终止信号给thread线程,成功返回0,但是成功并不意味着thread会终止

    5. pthread_testcancel():在不包含取消点,但是又需要取消点的地方创建一个取消点,以便在一个没有包含取消点的执行代码线程中响应取消请求.

    6. pthread_setcancelstate():设置本线程对cancle线程的反应

    7. pthread_setcanceltype():设置取消状态 继续运行至下一个取消点再退出或者是立即执行取消动作

    8. pthread_setcancel():设置取消状态

    三、线程互斥与同步机制 

    基本的互斥与同步的操作方法:

    1. pthread_mutex_init():互斥锁的初始化

    2. pthread_mutex_lock():锁定互斥锁,如果尝试锁定已经被上锁的互斥锁则阻塞至可用为止

    3. pthread_mutex_trylock():非阻塞的锁定互斥锁

    4. pthread_mutex_unlock():释放互斥锁

    5. pthread_mutex_destory():互斥锁销毁函数

    四、多线程实践

    1. 基本的线程及建立运行

    下面的代码是C/C++开发的基本的线程的运行,使用的就是最基本的pthread.h:

    /* thread.c */
    #include <stdio.h>
    #include <stdlib.h>
    #include <pthread.h>
     
    #define THREAD_NUMBER       3                 /*线程数*/
    #define REPEAT_NUMBER       5                 /*每个线程中的小任务数*/
    #define DELAY_TIME_LEVELS  10.0             /*小任务之间的最大时间间隔*/
    //
    void *thrd_func(void *arg) { 
        /* 线程函数例程 */
        int thrd_num = (int)arg;
        int delay_time = 0;
        int count = 0;
        printf("Thread %d is starting
    ", thrd_num);
        for (count = 0; count < REPEAT_NUMBER; count++) {
            delay_time = (int)(rand() * DELAY_TIME_LEVELS/(RAND_MAX)) + 1;
            sleep(delay_time);
            printf("	Thread %d: job %d delay = %d
    ", thrd_num, count, delay_time);
        }
     
        printf("Thread %d finished
    ", thrd_num);
        pthread_exit(NULL);
    }
     
    int main(void) {
         pthread_t thread[THREAD_NUMBER];
         int no = 0, res;
         void * thrd_ret;
         srand(time(NULL));    
         for (no = 0; no < THREAD_NUMBER; no++) {
              /* 创建多线程 */
              res = pthread_create(&thread[no], NULL, thrd_func, (void*)no);
              if (res != 0) {
                   printf("Create thread %d failed
    ", no);
                   exit(res);
              }
         }
     
         printf("Create treads success
     Waiting for threads to finish...
    ");
         for (no = 0; no < THREAD_NUMBER; no++) {
              /* 等待线程结束 */
              res = pthread_join(thread[no], &thrd_ret);
              if (!res) {
                printf("Thread %d joined
    ", no);
              } else {
                printf("Thread %d join failed
    ", no);
              }
         }
         return 0;        
    }

    例程中循环3次建立3条线程,并且使用pthread_join函数依次等待线程结束; 
    线程中使用rand()获取随机值随机休眠5次,随意会出现后执行的线程先执行完成; 
    运行结果:

    $ gcc thread.c -lpthread
    $ ./a.out 
    Create treads success
     Waiting for threads to finish...
    Thread 0 is starting
    Thread 1 is starting
    Thread 2 is starting
    Thread 1: job 0 delay = 2
    Thread 1: job 1 delay = 2
    Thread 0: job 0 delay = 8
    Thread 2: job 0 delay = 10
    Thread 2: job 1 delay = 3
    Thread 1: job 2 delay = 10
    Thread 0: job 1 delay = 8
    Thread 0: job 2 delay = 3
    Thread 0: job 3 delay = 1
    Thread 2: job 2 delay = 8
    Thread 1: job 3 delay = 8
    Thread 1: job 4 delay = 1
    Thread 1 finished
            Thread 2: job 3 delay = 6
            Thread 0: job 4 delay = 7
    Thread 0 finished
    Thread 0 joined
    Thread 1 joined
            Thread 2: job 4 delay = 10
    Thread 2 finished
    Thread 2 joined

    可以看到,线程1先于线程0执行,但是pthread_join的调用时间顺序,先等待线程0执行; 
    由于线程1已经早结束,所以线程0被pthread_join等到的时候,线程1已结束,就在等待到线程1时,直接返回; 

    2. 线程执行的互斥和同步pthread_mutex_lock

    下面我们在上面的程序中增加互斥锁:

    /*thread_mutex.c*/
    #include <stdio.h>
    #include <stdlib.h>
    #include <pthread.h>
    #include <unistd.h>
     
    #define THREAD_NUMBER        3            /* 线程数 */
    #define REPEAT_NUMBER        3            /* 每个线程的小任务数 */
    #define DELAY_TIME_LEVELS 10.0         /*小任务之间的最大时间间隔*/
    pthread_mutex_t mutex;
     
    void *thrd_func(void *arg) {
         int thrd_num = (int)arg;
         int delay_time = 0, count = 0;
         int res;
         /* 互斥锁上锁 */
         res = pthread_mutex_lock(&mutex);
         if (res) {
              printf("Thread %d lock failed
    ", thrd_num);
              pthread_exit(NULL);
         }
         printf("Thread %d is starting
    ", thrd_num);
         for (count = 0; count < REPEAT_NUMBER; count++) {          
             delay_time = (int)(rand() * DELAY_TIME_LEVELS/(RAND_MAX)) + 1;
             sleep(delay_time);
             printf("	Thread %d: job %d delay = %d
    ", 
                                          thrd_num, count, delay_time);
         }
         printf("Thread %d finished
    ", thrd_num);
         /****互斥锁解锁***/
         pthread_mutex_unlock(&mutex);
         pthread_exit(NULL);
    }
     
    int main(void) {
         pthread_t thread[THREAD_NUMBER];
         int no = 0, res;
         void * thrd_ret;
     
         srand(time(NULL));
         /* 互斥锁初始化 */
         pthread_mutex_init(&mutex, NULL);
         for (no = 0; no < THREAD_NUMBER; no++) {
              res = pthread_create(&thread[no], NULL, thrd_func, (void*)no);
              if (res != 0) {
                  printf("Create thread %d failed
    ", no);
                  exit(res);
              }
         }     
         printf("Create treads success
     Waiting for threads to finish...
    ");
         for (no = 0; no < THREAD_NUMBER; no++) {
              res = pthread_join(thread[no], &thrd_ret);
              if (!res) {
                    printf("Thread %d joined
    ", no);
              } else  {
                  printf("Thread %d join failed
    ", no);
              }
         }   
         pthread_mutex_destroy(&mutex);          
         return 0;        
    }

    在上面的例程中直接添加同步锁pthread_mutex_t; 
    在线程中加入,程序在执行线程程序时,调用pthread_mutex_lock上锁,发现上锁时候后进入等待,等待锁再次释放后重新上锁; 
    所以线程程序加载到队列中等待,等待成功上锁后继续执行程序代码; 
    运行结果如下:

    Create treads success
     Waiting for threads to finish...
    Thread 0 is starting
        Thread 0: job 0 delay = 7
        Thread 0: job 1 delay = 2
        Thread 0: job 2 delay = 9
    Thread 0 finished
    Thread 2 is starting
    Thread 0 joined
        Thread 2: job 0 delay = 6
        Thread 2: job 1 delay = 7
        Thread 2: job 2 delay = 10
    Thread 2 finished
    Thread 1 is starting
        Thread 1: job 0 delay = 3
        Thread 1: job 1 delay = 5
        Thread 1: job 2 delay = 2
    Thread 1 finished
    Thread 1 joined
    Thread 2 joined 
  • 相关阅读:
    mybatis 错误 Invalid bound statement (not found)
    Redis is configured to save RDB snapshots, but is currently not able to persist on disk. Commands that may modify the data set are disabled. Please check Redis logs for details about the error.
    bug 记录 Unable to start ServletWebServerApplicationContext due to multiple ServletWebServerFactory beans
    解决:The Tomcat connector configured to listen on port 8182 failed to start. The port may already be in use or the connector may be misconfigured.
    jquery validate 验证插件 解决多个相同的Name 只验证第一个的方案
    phpStorm+xdebug调试(php7.3)
    小程序视频多个视频播放与暂停
    CSS实现单行、多行文本溢出显示省略号(…)
    Packet for query is too large (4,544,730 > 4,194,304). You can change this value on the server by setting the 'max_allowed_packet' variable.
    idea自动在文件头中添加作者和创建时间
  • 原文地址:https://www.cnblogs.com/renhui/p/9900509.html
Copyright © 2011-2022 走看看