zoukankan      html  css  js  c++  java
  • [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);



  • 相关阅读:
    hdu 1028 Ignatius and the Princess III (n的划分)
    CodeForces
    poj 3254 Corn Fields (状压DP入门)
    HYSBZ 1040 骑士 (基环外向树DP)
    PAT 1071 Speech Patterns (25)
    PAT 1077 Kuchiguse (20)
    PAT 1043 Is It a Binary Search Tree (25)
    PAT 1053 Path of Equal Weight (30)
    c++ 常用标准库
    常见数学问题
  • 原文地址:https://www.cnblogs.com/li-daphne/p/5325017.html
Copyright © 2011-2022 走看看