为了账号安全,请及时绑定邮箱和手机立即绑定

详解线程的信号量和互斥锁

详解线程的信号量和互斥锁

文章出处:liudw---原文地址

  前言:有个问题感觉一直会被问道:进程和线程的区别?也许之前我会回答:

  • 进程:资源分配最小单位

  • 线程:轻量级的进程 是系统调度的最小单位 由进程创建 多个线程共享进程的资源

  但是现在我觉得一个比喻回答的更好:程序就像静止的火车,进程是运行的火车,线程是运行火车的每节车厢。

个人感觉理解远比背些概念性东西更好。

  一、线程

  通常在一个进程中可以包含若干个线程,当然一个进程中至少有一个线程,不然没有存在的意义。线程可以利用进程所拥有的资源,在引入线程的操作系统中,通常都是把进程作为分配资源的基本单位,而把线程作为独立运行和独立调度的基本单位,由于线程比进程更小,基本上不拥有系统资源,故对它的调度所付出的开销就会小得多,能更高效的提高系统多个程序间并发执行的程度。

  1、线程相关函数 

  • pthread_create函数

#include <pthread.h>

int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine) (void *), void *arg);

注:Compile and link with -pthread.//编译时 要加-lpthread 
功能:创建线程
参数1:线程的ID 
参数2:NULL 
参数3:线程处理函数
参数4: 传递给线程处理函数的参数
成功放回0 失败返回-1

  • pthread_join函数

#include <pthread.h>

int pthread_join(pthread_t thread, void **retval);

功能:以阻塞的方式等待指定线程 主线程如果执行到此函数 将阻塞等待子线程结束

  程序1-1演示两个函数用法:

复制代码

#include"my.h"void *func(void *p) 
{    *(int*)p = 10; 
    printf("%d\n",*(int *)p);
}int main()
{    int x=100;
    pthread_t id; 
    int ret = pthread_create(&id,NULL,func,&x);    if(ret<0)
    {   
        perror("pthread_create");
        exit(-1);
    }   
    pthread_join(id,NULL);    return 0;

}

复制代码

注:头文件“my.h”为自定义文件,详情请参考这篇博客:http://www.cnblogs.com/liudw-0215/p/8946879.html  

运行演示如下图:

https://img1.sycdn.imooc.com//5ae481560001ea1910130197.jpg

  二、信号量

  信号量(Semaphore),有时被称为信号灯,是在多线程环境下使用的一种设施, 它负责协调各个线程, 以保证它们能够正确、合理的使用公共资源。

  1、信号量相关函数

  • sem_init函数

sem_t s;

#include <semaphore.h>

int sem_init(sem_t *sem, int pshared, unsigned int value);

格式:sem_init(&s,0,n)
功能:初始化一个信号量的值为value
参数2:是否在进程间使用 一般总是0 表示不在进程间使用
参数3:计数器的初始值

  • sem_wait函数

int sem_wait(sem_t *sem);
把计数器减一 它会等待 直到信号量有个非零值才会执行减法操作
如果对值为0的信号量用sem_wait 这个函数会等待 直到其他线程增加该信号量的值 使其不再是0为止
如果对值为2的信号量调用sem_wait 线程会继续执行 但信号量的值会减一。
如果两个线程同时在sem_wait调用上等待同一个信号量变为非0值 那么当信号量 被第三个线程+1 只有一个等待线程开始对信号量-1 
然后继续执行 另一个线程还继续等待。

  • sem_post函数

#include <semaphore.h>

int sem_post(sem_t *sem);

功能:把 计数器+1

  程序2-1介绍信号量使用

复制代码

#include"my.h"sem_t s;void *fun(void *p)
{    int i;    int *pa = (int *)p;    for(i=0;i<4;i++)
    {
        sem_wait(&s);//将计数器的值-1 
        pa[i] +=i;
    }    for(i=0;i<4;i++)
    {
        printf("%-02d",pa[i]);
    }
    printf("\n");    return  NULL;
}void *fun1(void *p)
{
    sem_wait(&s);//将计数器的值-1 
    puts("fun1 run!");    return NULL;
}int main()
{    int i=0,ret=0;    int a[5]={0};
    sem_init(&s,0,0);//设置信号量的值为0
    pthread_t tid[2];
    ret = pthread_create(&tid[0],NULL,fun,a);    if(ret<0)
    {
        perror("pthread_create");
        exit(-1);
    }
    ret = pthread_create(&tid[1],NULL,fun1,a);    if(ret<0)
    {
        perror("pthread_create");
        exit(-1);
    }    for(i=0;i<5;i++)
    {
        sem_post(&s);//将计数器的值+1      }

    pthread_join(tid[0],NULL);
    pthread_join(tid[1],NULL);    return 0;
}

复制代码

运行演示如下图:

https://img1.sycdn.imooc.com//5ae481820001a81d09840230.jpg

  三、互斥锁

  互斥锁: 只要被锁住,其他任何线程都不可以访问被保护的资源

  1、互斥锁相关函数

pthread_mutex_t m;

pthread_mutex_init(&m,NULL) //初始化互斥量
pthread_mutex_lock(&m);//对一个互斥量加锁 如果互斥量已经加锁 函数会一直等待 等到有线程把这个互斥量解锁后 再去加锁
pthread_mutex_unlock(&m);//对一个互斥量解锁 哪个线程加锁只能由这个线程解锁 别的线程不能 解锁

  程序3-1演示互斥锁应用:

复制代码

#include"my.h"pthread_mutex_t m;void* thread_fun(void  *p)
{    int i;
    pthread_mutex_lock(&m);//加锁
    for(i=0;i<3;i++)
    {
        printf("PID:%d tid:%lu\n",getpid(),pthread_self());
        sleep(1);
    }
    pthread_mutex_unlock(&m);//解锁    pthread_exit(NULL);
}int main()
{
    pthread_mutex_init(&m,NULL);//初始化锁
    int i,ret;
    pthread_t tid[3];    for(i=0;i<3;i++)
    {
        ret = pthread_create(&tid[i],NULL,thread_fun,NULL);        if(ret<0)
        {
            printf("pthread_create  %d error\n",i);
            exit(-1);
        }
    }    
    
    
    for(i=0;i<3;i++)
    {
        pthread_join(tid[i],NULL);
    }    return 0;
}

复制代码

  运行演示如下图:

https://img1.sycdn.imooc.com//5ae481a7000129aa10220524.jpg

总结:主要介绍线程同步的信号量和互斥锁,以后有时间将更加详细介绍其中实现原理。


点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消