• [linux basic 基础]----同步信号量


    直接使用一个共享变量,来是两个线程之间进行切换是非常笨拙而且没有效率的;
    信号量--
    互斥量--
    这两者是相互通过对方来实现的;
    比如,如果想控制某一时刻只有一个线程可以访问一些共享内存,使用互斥量要自然一些;
    但是控制一组相同的对下的访问时,比如同5条可用的电话线中分配1条给某个可用的线程,那么使用计数信号量;
    -------------------------------------

    信号量,是一个特殊类型的变量,它可以被增加或减少,但对其的关键访问被保证是原子操作,及时一个多线程程序也是如比;
    意味着如果两个(更多)的现场试图改变一个信号量的值,系统保证所有的操作都将一次进行
    信号量,二进制信号量只有0/1两种取值,还有一种更通用的信号量--计数信号量;
    信号量函数的名字以sem_开头,而不像大多数线程函数那样以pthread_开头
    基本信号量函数有四个:
    ---
    #include<semaphore.h>
    int sem_init(sem_t *sem,int psthared, unsigned int value);
    信号量通过这个函数来创建,由sem指向的信号量对象,设置他的共享参数,给一个初始的整数值
    psthared,控制信号量的类型,其值为0,表示这个信号量是当前进程的局部信号量,否则该信号量可以在多个进程见共享
    ---
    #include <semaphore.h>
    int sem_wait(sem_t *sem);
    wait函数将信号量的减到1,但是会等到新好两有个非零值才会开始减法操作;
    如果对为0的信号量调用sem_wait函数,函数会等待,知道其他线程增加了该信号量的值使其!=0;

    ---
    #include <semaphore.h>
    int sem_post(sem_t *sem);
    post函数作用是以原子操作的方式将信号量的值+1;
    描述:”在单个函数中就能原子化地进行测试和设置“的能力很有价值;
    ---
    sem_trywait()是sem_wait的非阻塞版本
    以一个信号量指针为参数,清理该信号量拥有的所有资源,如果企图清理信号量正被一个线程等待,返回一个错误
    ---
    #include <semaphore.h>
    int sem_destroy(sem_t *sem);


    ==============
    例子;
    /*************************************************************************
        > File Name: thread3.c
        > Author: 
        > Mail: 
        > Created Time: 2016年03月27日 星期日 10时01分36秒
     ************************************************************************/
    
    #include<stdio.h>
    #include<unistd.h>
    #include<stdlib.h>
    #include<string.h>
    #include<pthread.h>
    #include<semaphore.h>
    
    void *thread_function(void *arg);
    sem_t bin_sem;
    
    #define WORK_SIZE 1024
    char work_area[WORK_SIZE];
    
    int main(){
        int res;
        pthread_t a_thread;
        void *thread_result;
    
        res = sem_init(&bin_sem,0,0);
        if(res != 0){
            perror("semaphore initialization failed");
            exit(EXIT_FAILURE);
        }
    
        res = pthread_create(&a_thread,NULL,thread_function,NULL);
        if(res!=0){
            perror("thread creation failed");
            exit(EXIT_FAILURE);
        }else{
            printf("thread creation successful
    ");
        }
    
        printf("input some text, Enter 'end' to finish
    ");
        while(strncmp("end",work_area,3) != 0){
            fgets(work_area,WORK_SIZE,stdin);
            int res = sem_post(&bin_sem);
            if(res != 0){
                printf("sem_post failed
    ");
                exit(EXIT_FAILURE);
            }else{
                printf("sem_post seccussful,bin_sem = 
    ");
            }
        }
    
        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
    ");
        sem_destroy(&bin_sem);
        exit(EXIT_SUCCESS);
    }
    
    
    void *thread_function(void *arg){
        printf("begin thread_function
    ");
        int w = sem_wait(&bin_sem);
        if(w != 0){
            printf("sem_wait_1 failed
    ");
            exit(EXIT_FAILURE);
        }else{
            printf("sem_wait_1 seccussful
    ");
        }
    
        while(strncmp("end",work_area,3) != 0){
            printf("you input %d characters
    ",strlen(work_area)-1);
            sem_wait(&bin_sem);
        }
        printf("----
    ");
        pthread_exit(NULL);
    }

    编译方法:

    lizhen@lizhen:~/basic$ cc -D_REENTANT thread3.c -o thread3 -lpthread
    thread3.c: In function ‘thread_function’:
    thread3.c:76:9: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘size_t’ [-Wformat=]
             printf("you input %d characters
    ",strlen(work_area)-1);
             ^
    lizhen@lizhen:~/basic$ 

    运行情况:

    [code=c]
    lizhen@lizhen:~/basic$ ./thread3 
    thread creation successful
    input some text, Enter 'end' to finish
    begin thread_function
    kl
    sem_post seccussful,bin_sem = 
    sem_wait_1 seccussful
    you input 2 characters
    end
    sem_post seccussful,bin_sem = 
    ----

    代码分析:

    为什么不能看到thread_function 线程函数返回,接着执行main()主线程的结尾部分;而是好像一直等待什么??
    这是一个信号量同步的问题,
    main()接受输入,
    当输入的字符串不是“end”时,thread_function()计算字符串的长度并输出
    ,利用信号量bin_sem来控制main()与thread_function()的执行;
    =====================
    结论,我自己找到问题所在了,
    因为在main()中,while判断中,strcmp(“end”,“work_area”,3) !=0 中,
    work_area不应该加双引号的,
    main()中,while()循环会一直执行下去,接受fgets()输入,sem_post(&bin_sem);
    thread_function()线程中的while开始执行,当work_area不是“end”时打印字符串的长度;当work_area是“end”的时候跳出while()循环,执行pthread_exit(NULL);线程结束
    但是main中的while()会一直循环下去的,因为它的判断条件一直“为真”,会一直等待输入,对信号量执行sem_post(&bin_sem);



  • 相关阅读:
    源码解析.Net中IConfiguration配置的实现
    python小工具
    hue搭建以及报错记录
    jenkins启动指定数据目录
    基于三维地图的智慧园区可视化解决方案
    工业4.0的下一个十年
    项目管理知识体系介绍
    人工智能发展的新方向
    速成财务产品经理
    标准化体系:运营—训练—督导
  • 原文地址:https://www.cnblogs.com/li-daphne/p/5325017.html
Copyright © 2020-2023  润新知