zoukankan      html  css  js  c++  java
  • 临界区

    临界区

    2019519

    18:46

       

    多个线程在同时调用函数时可能会产生问题,可能会产生问题的这部分代码称之为临界区(Critical Section)。

    根据临界区是否会产生问题,函数可分为:

    • 线程安全函数(Threa-safe function)
    • 非线程安全函数(Thread-unsafe function)

       

    线程安全函数被多个线程同时调用也没有问题,但是非线程安全函数就可能会引发问题。

    大多数标准函数都是线程安全函数,我们不需要自己区分线程安全函数与非线程安全函数。因为他们大都数时候都提供了非线程安全函数的对应线程安全版本。

    在涉及线程的代码中,我们可以同在在头文件声明前定义_REENTRANT宏来说明调用线程安全函数

    也可以通过在编译时添加-D_REENTRANT选项定义宏

       

    $ gcc -D_REENTRANT mythread.c -o mythread -lpthread

       

    线程存在的问题和临界区

    任何内存空间只要是被线程同时访问,就有可能发生问题。

    为了解决这个临界区的问题其实很简单,就是不让不同线程同时访问一个变量。而实现这个就是 线程同步

    线程同步可以解决两方面的情况:

    • 不能同时访问同一内存空间
    • 需要指定访问同一内存空间的线程执行顺序

       

    互斥量 Mutual Exclusion

    表示不允许多个线程同时访问,互斥量主要用于结局线程同步的问题。

    我们通过互斥量实现互斥锁,在一个线程在访问变量时就将他锁住,而等到访问完毕再释放这把锁。

       

    创建与删除互斥量

    #include <pthread.h>

    int pthread_mutex_init(pthread_mutex_t *mutex,

    const pthread_mutexattr_t *attr);

    int pthread_mutex_destroy(pthread_mutex_t *mutex);

    ->>成功时返回0,失败时返回其他值

       

    mutex: 互斥量指针

    attr:创建互斥量需要指定的属性,默认值则传递NULL

       

    上锁与解锁

    #include <pthread.h>

    int pthread_mutex_lock(pthread_mutex_t *mutex);

    int pthread_mutex_unlock(pthread_mutex_t *mutex);

       

    当其他线程调用pthread_mutex_lock函数预备进入临界区时,如果发现有其他线程已经进入临界区。将使这个函数阻塞,一直到那个线程调用pthread_mutex_unlock解锁

       

    pthread_mutex_lock(&mutex);

    // 临界区开始

    // ….

    //临界区结束

    pthread_mutex_unlock(&mutex);

       

    如果线程退出临界区使,而没有调用pthread_mutex_unlock函数,那么其他线程的pthread_mutex_lock函数将一直处于阻塞状态。这种情况称之为死锁。

       

    互斥量lock,unlock函数的频繁调用使程序的执行效率降低。所以应该对于不同的程序适当的考虑是应该扩大还是缩小临界区。

       

    信号量 Semaphore

    顾名思义。与互斥量的开锁与解锁相比。信号量就是给一个信号,看是否复合条件能通过。

       

    信号量的创建和销毁

    #include <semaphore.h>

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

    int sem_destroy(sem_t *sem);

    ->>成功时返回0,失败时返回其他值

       

    sem: 保存信号量的地址

    pshared: 传递其他值是,创建可有多个进程共享的信号量。传递0时,只允许一个进程内部使用。

    value:信号量的初始值

       

    相当于互斥量的开锁与解锁的函数

    #include <semaphore.h>

    int sem_post(sem_t *sem);

    int sem_wait(sem_t *sem);

    ->>成功时返回0,失败时返回其他值

       

    sem:保存信号量的地址

    传递给sem_post函数时增加1

    传递给sem_wait函数时减少1,当信号量值必须大于等于0

       

    也就是通过调用sem_wait函数时检查信号量的值是否满足要求才继续下去,否则就阻塞。等到其他线程调用sem_post使这个信号量满足要求。

    调用sem_wait函数进入临界区的线程再调用sem_post函数前不允许其他线程进入临界区。信号量的值在0和1之间跳转。具有这种特性的机制被称为"二进制信号量"。

  • 相关阅读:
    java 中静态变量和实例变量之间的区别
    java 中final 引用不可变,但是引用还是可以发生变化的
    java中char和Unicode之间的关系
    java 中终止内层循环的方法
    ssh 公钥免密码登陆
    关于Python 中unicode 转码的问题
    Python中Unicode码和非Unicode码引起的错误与格式转换
    第一次写博客,怎么写?
    zookeeper实现主-从结构的一般原理
    Python中Tuple的词源有趣探索
  • 原文地址:https://www.cnblogs.com/freesfu/p/10890631.html
Copyright © 2011-2022 走看看