zoukankan      html  css  js  c++  java
  • Linux _pthread 线程的同步 浅见

    线程的同步

    1. 问题
      同一个进程内的各个线程,共享该进程内的全局变量
      如果多个线程同时对某个全局变量进行访问时,就可能导致竞态。

      解决办法,对临界区使用信号量、或互斥量。

    2. 信号量和互斥量的选择。
      对于同步和互斥,使用信号量或互斥量都可以实现。
      使用时,选择更符合语义的手段:
      如果要求最多只允许一个线程进入临界区,则使用互斥量
      如果要求多个线程之间的执行顺序满足某个约束,则使用信号量

    3. 信号量
      1)什么是信号量
      此时所指的“信号量”是指用于同一个进程内多个线程之间的信号量。
      即POSIX信号量,而不是System V信号量(用于进程之间的同步)

       用于线程的信号量的原理,与用于进程之间的信号量的原理相同。
       都有P操作、V操作。
      
       信号量的表示:sem_t  类型
      

      2) 信号量的初始化
      sem_init
      原型:int sem_init (sem_t *sem, int pshared, unsigned int value);
      功能:对信号量进行初始化
      参数:sem, 指向被初始化的信号量
      pshared, 0:表示该信号量是该进程内使用的“局部信号量”, 不再被其他进程共享。
      非0:该信号量可被其他进程共享,Linux不支持这种信号量
      value, 信号量的初值。

      = 0
      返回值:成功,返回0
      失败, 返回错误码

      3) 信号量的P操作
      sem_wait
      原型:int sem_wait (sem_t *sem);
      返回值:成功,返回0
      失败, 返回错误码

      4) 信号量的V操作
      sem_post
      原型:int sem_post (sem_t *sem);
      返回值:成功,返回0
      失败, 返回错误码

      5) 信号量的删除
      sem_destroy
      原型:int sem_destroy (sem_t *sem);
      返回值:成功,返回0
      失败, 返回错误码

      6) 实例
      主线程循环输入字符串,把字符串存放到一个全局缓存中。
      新线程从全局缓存中读取字符串,统计该字符串的长度。
      直到用户输入end
      main1.c

      创建2个线程(共有主线程、线程1、线程2共3个线程)
      主线程阻塞式等待用户输入字符串
      主线程每接收到一个字符串之后, 线程1就马上对该字符串进行处理。
      线程1的处理逻辑为:统计该字符串的个数,并记录当时的时间。
      线程1把该字符串处理完后,线程2马上就把处理结果写入文件result.txt
      直到用户输入exit.
      multi_pthread.c
      
    4. 互斥量
      1)什么是互斥量
      效果上等同于初值为1的信号量

       互斥量的使用:类型为 pthread_mutex_t
      

      2)互斥量的初始化
      pthread_mutex_init
      原型:int pthread_mutex_init(pthread_mutex_t *mutex,
      pthread_mutexattr_t *attr);
      参数:mutex, 指向被初始化的互斥量
      attr, 指向互斥量的属性
      一般取默认属性(当一个线程已获取互斥量后,该线程再次获取该信号量,将导致死锁!)

      3) 互斥量的获取
      pthread_mutex_lock
      原型:int pthread_mutex_lock (pthread_mutex_t *mutex);

      4)互斥量的释放
      pthread_mutex_unlock
      原型:int pthread_mutex_unlock (pthread_mutex_t *mutex);

      5)互斥量的删除
      pthread_mutex_destroy
      int pthread_mutex_destroy (pthread_mutex_t *mutex);

      6) 实例
      最简单的互斥量使用
      main2.c

      main3.c
      (1) 分析程序的功能
      (2) 分析程序存在的隐患
      (3) 用互斥量解决该程序的隐患 (不能删除、修改代码,只能添加代码)         
           修改后为main4.c
      
    void work(char *str)
    {
        char *p = str;
        while(*p) {
            if (*p >= 'a' && *p <= 'z') {
                    *p = *p - 'a' + 'A';
            }
        }
    
    }
    
    
    time_t time;
    time(&time);
    char *p = ctime(&time);

    main1.c

    #include <pthread.h>
    #include <semaphore.h>
    #include <string.h>
    #include <stdlib.h>
    #include <stdio.h>
    
    #define BUFF_SIZE 80
    
    char buff[BUFF_SIZE];
    sem_t sem;
    
    static void* str_thread_handle(void *arg) 
    {
        while(1) {
            //P(sem)
            if (sem_wait(&sem) != 0) {
                printf("sem_wait failed!
    ");
                exit(1);
            }
    
            printf("string is: %slen=%d
    ", buff, strlen(buff));
            if (strncmp(buff, "end", 3) == 0) {
                break;
            }
        }
    }
    
    int main(void)
    {
        int ret;
        pthread_t  str_thread;
        void *thread_return;
    
    
    
        ret = sem_init(&sem, 0, 0);
        if (ret != 0) {
            printf("sem_init failed!
    ");
            exit(1);
        }
    
        ret = pthread_create(&str_thread, 0, str_thread_handle, 0);
        if (ret != 0) {
            printf("pthread_create failed!
    ");
            exit(1);
        }
    
        while (1) {
            fgets(buff, sizeof(buff), stdin);
    
            //V(sem)
            if (sem_post(&sem) != 0) {
                printf("sem_post failed!
    ");
                exit(1);
            }
    
            if (strncmp(buff, "end", 3) == 0) {
                break;
            }
        }
    
        ret = pthread_join(str_thread, &thread_return);
        if (ret != 0) {
            printf("pthread_join failed!
    ");
            exit(1);
        }
    
        ret = sem_destroy(&sem);
        if (ret != 0) {
            printf("sem_destroy failed!
    ");
            exit(1);
        }
    
        return 0;
    }
    

    main2.c

    #include <pthread.h>
    #include <semaphore.h>
    #include <string.h>
    #include <stdlib.h>
    #include <stdio.h>
    
    #define BUFF_SIZE 80
    
    int global_value = 1000;
    pthread_mutex_t  lock;
    
    static void* str_thread_handle(void *arg) 
    {
        int i = 0;
    
        for (i=0; i<10; i++) {
            //pthread_mutex_lock(&lock);
    
            if (global_value  > 0) {
                // work
                sleep(1);
                printf("soled ticket(%d) to ChildStation(%d)
    ",
                    global_value, i+1);
            }
            global_value--;
    
            //pthread_mutex_unlock(&lock);
            sleep(1);
        }
    }
    
    int main(void)
    {
        int ret;
        pthread_t  str_thread;
        void *thread_return;
        int i;
    
    
    
        ret = pthread_mutex_init(&lock, 0);
        if (ret != 0) {
            printf("pthread_mutex_init failed!
    ");
            exit(1);
        }
    
        ret = pthread_create(&str_thread, 0, str_thread_handle, 0);
        if (ret != 0) {
            printf("pthread_create failed!
    ");
            exit(1);
        }
    
        for (i=0; i<10; i++) {
            //pthread_mutex_lock(&lock);
    
            if (global_value  > 0) {
                // work
                sleep(1);
                printf("soled ticket(%d) to MainStation(%d)
    ",
                    global_value, i+1);
            }
            global_value--;
    
    
            //pthread_mutex_unlock(&lock);
            sleep(1);
        }
    
        ret = pthread_join(str_thread, &thread_return);
        if (ret != 0) {
            printf("pthread_join failed!
    ");
            exit(1);
        }
    
        ret = pthread_mutex_destroy(&lock);
        if (ret != 0) {
            printf("pthread_mutex_destroy failed!
    ");
            exit(1);
        }
    
        return 0;
    }
    

    main3.c

    #include <stdio.h>
    #include <unistd.h>
    #include <stdlib.h>
    #include <string.h>
    #include <pthread.h>
    #include <semaphore.h>
    
    void *thread_function(void *arg);
    
    #define WORK_SIZE 1024
    char work_area[WORK_SIZE];
    int time_to_exit = 0;
    
    int main() 
    {
        int res;
        pthread_t a_thread;
        void *thread_result;
    
        res = pthread_create(&a_thread, NULL, thread_function, NULL);
        if (res != 0) {
            perror("Thread creation failed");
            exit(EXIT_FAILURE);
        }
    
        printf("Input some text. Enter 'end' to finish
    ");
        while(!time_to_exit) {
            fgets(work_area, WORK_SIZE, stdin);
            while(1) {
                if (work_area[0] != '') {
                    sleep(1);
                }
                else {
                    break;
                }
            }
        }
    
        printf("
    Waiting for thread to finish...
    ");
        res = pthread_join(a_thread, &thread_result);
        if (res != 0) {
            perror("Thread join failed");
            exit(EXIT_FAILURE);
        }
        printf("Thread joined
    ");
    
        exit(EXIT_SUCCESS);
    }
    
    void *thread_function(void *arg) 
    {
        sleep(1);
    
        while(strncmp("end", work_area, 3) != 0) {
            printf("You input %d characters
    ", strlen(work_area) -1);
            work_area[0] = '';
            sleep(1);
            while (work_area[0] == '' ) {
                sleep(1);
            }
        }
        time_to_exit = 1;
        work_area[0] = '';
        pthread_exit(0);
    }

    main4.c

    #include <stdio.h>
    #include <unistd.h>
    #include <stdlib.h>
    #include <string.h>
    #include <pthread.h>
    #include <semaphore.h>
    
    void *thread_function(void *arg);
    pthread_mutex_t work_mutex; /* protects both work_area and time_to_exit */
    
    #define WORK_SIZE 1024
    char work_area[WORK_SIZE];
    int time_to_exit = 0;
    
    int main() {
        int res;
        pthread_t a_thread;
        void *thread_result;
        res = pthread_mutex_init(&work_mutex, NULL);
        if (res != 0) {
            perror("Mutex initialization failed");
            exit(EXIT_FAILURE);
        }
        res = pthread_create(&a_thread, NULL, thread_function, NULL);
        if (res != 0) {
            perror("Thread creation failed");
            exit(EXIT_FAILURE);
        }
        pthread_mutex_lock(&work_mutex);
        printf("Input some text. Enter 'end' to finish
    ");
        while(!time_to_exit) {
            fgets(work_area, WORK_SIZE, stdin);
            pthread_mutex_unlock(&work_mutex);
            while(1) {
                pthread_mutex_lock(&work_mutex);
                if (work_area[0] != '') {
                    pthread_mutex_unlock(&work_mutex);
                    sleep(1);
                }
                else {
                    break;
                }
            }
        }
        pthread_mutex_unlock(&work_mutex);
        printf("
    Waiting for thread to finish...
    ");
        res = pthread_join(a_thread, &thread_result);
        if (res != 0) {
            perror("Thread join failed");
            exit(EXIT_FAILURE);
        }
        printf("Thread joined
    ");
        pthread_mutex_destroy(&work_mutex);
        exit(EXIT_SUCCESS);
    }
    
    void *thread_function(void *arg) {
        sleep(1);
        pthread_mutex_lock(&work_mutex);
        while(strncmp("end", work_area, 3) != 0) {
            printf("You input %d characters
    ", strlen(work_area) -1);
            work_area[0] = '';
            pthread_mutex_unlock(&work_mutex);
            sleep(1);
            pthread_mutex_lock(&work_mutex);
            while (work_area[0] == '' ) {
                pthread_mutex_unlock(&work_mutex);
                sleep(1);
                pthread_mutex_lock(&work_mutex);
            }
        }
        time_to_exit = 1;
        work_area[0] = '';
        pthread_mutex_unlock(&work_mutex);
        pthread_exit(0);
    }
    
  • 相关阅读:
    将vue文件script代码抽取到单独的js文件
    git pull 提示错误:Your local changes to the following files would be overwritten by merge
    vue和uniapp 配置项目基础路径
    XAMPP Access forbidden! Access to the requested directory is only available from the local network.
    postman与newman集成
    postman生成代码段
    Curl命令
    POST方法的Content-type类型
    Selenium Grid 并行的Web测试
    pytorch转ONNX以及TnesorRT的坑
  • 原文地址:https://www.cnblogs.com/Sico2Sico/p/5384201.html
Copyright © 2011-2022 走看看