积少成多

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::
直接使用一个共享变量,来是两个线程之间进行切换是非常笨拙而且没有效率的;
信号量--
互斥量--
这两者是相互通过对方来实现的;
比如,如果想控制某一时刻只有一个线程可以访问一些共享内存,使用互斥量要自然一些;
但是控制一组相同的对下的访问时,比如同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\n");
    }

    printf("input some text, Enter 'end' to finish\n");
    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\n");
            exit(EXIT_FAILURE);
        }else{
            printf("sem_post seccussful,bin_sem = \n");
        }
    }

    printf("\nWaiting for thread to finish...\n");
    res = pthread_join(a_thread, &thread_result);
    if(res!=0){
        perror("thread join failed");
        exit(EXIT_FAILURE);
    }

    printf("thread joined\n");
    sem_destroy(&bin_sem);
    exit(EXIT_SUCCESS);
}


void *thread_function(void *arg){
    printf("begin thread_function\n");
    int w = sem_wait(&bin_sem);
    if(w != 0){
        printf("sem_wait_1 failed\n");
        exit(EXIT_FAILURE);
    }else{
        printf("sem_wait_1 seccussful\n");
    }

    while(strncmp("end",work_area,3) != 0){
        printf("you input %d characters\n",strlen(work_area)-1);
        sem_wait(&bin_sem);
    }
    printf("----\n");
    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\n",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);

 




posted on 2016-03-27 10:01  x7b5g  阅读(451)  评论(0编辑  收藏  举报