• Linux多线程编程——线程的同步


    POSIX信号量
    posix信号量不同于IPC中的信号量 
    常用的posix信号量函数
     
    #include <semaphore.h>
    int sem_init(sem_t* sem,int pshared,unsigned int value);
    //初始化一个信号量,pshared参数指定信号量的类型,若为0,表示信号量为当前进程的局部信号量,否则,该信号量就可以在多个进程之间共享。value参数指定信号量的初始值。
     
    int sem_destroy(sem_t* sem);
    //销毁一个信号量,释放它所占有的内核资源
     
    int sem_wait(sem_t* sem);
    //让信号量的值减一,如果信号量的值为0,则阻塞,直到信号量的值为非0.
     
    int sem_trywait(sem_t* sem);
    //sem_wait的非阻塞版本,若信号量的值为0,返回一个错误值 -1,并设置errno为EAGAIN.
     
    int sem_post(sem_t* sem);
    //让信号量的值加1,当信号量的值大于0时,其他正在调用sem_wait的函数将被唤醒。
     
    上面这写函数成功返回0,失败返回-1.
    互斥锁

    互斥量相当与锁,在使用共享资源时,对它加锁,使用完后,释放锁,在加锁期间,其他的线程不能对该共享资源进行操作.

    数据类型:pthread_mutex_t

    相关API

    初始化和销毁互斥量

    初始化一个互斥量时也可以赋值为PTHREAD_MUTEX_INITIALIZER

    int pthread_mutex_init(pthread_mutext_t *restrict mutex, const pthread_mutexattr_t *restrict attr);

    //attr设置为NULL,代表以默认属性初始化互斥量

    int pthread_mutex_destroy(pthread_mutex_t *mutex);

    加锁

    int pthread_mutex_lock(pthread_mutex_t *mutex);

    //对互斥量加锁,若互斥量已加锁,则会阻塞,直到信号量解锁,成功返回0,

    int pthread_mutex_trylock(pthread_mutex_t *mutex);

    //如果信号量没被锁,则加锁,并返回0,若信号已被锁,则不会阻塞,返回一个非0值

    int pthread_mutex_unlock(pthread_mutex_t *mutex);

    int pthread_mutex_timedlock(pthread_mutex_t *restrict mutex,const struct timespec *restrict tsptr);

    //当线程试图获取一个已经加锁的互斥量时,该函数可以设置等待时间,若在该时间内,互斥量被解锁,则调用该函数的线程可以继续运行,若没有解锁,则该函数不会对互斥量加锁,而是返回一个错误代码ETIMEDOUT,成功返回0

    #include <stdlib.h>
    #include <unistd.h>
    
    struct foo
    {
        int f_count;
        pthread_mutex_t f_lock;
        int f_id;
    };
    
    struct foo* foo_alloc(int id)
    {
        struct foo * fp;
        if((fp=malloc(sizeof(struct foo))!=NULL)
        {
            fp->f_count=1;
            fp->f_id=id;
            if(pthread_mutex_init(&fp->f_lock,NULL)!=0)
            {
                free(fp);
                return (NULL);
            }
        }
    
        return (fp);
    }
    
    void foo_hold(struct foo * fp)
    {
        pthread_mutex_lock(&fp->f_lock);
        fp->f_count++;
        pthread_mutex_unlock(&fp->f_lock);
    }
    
    void foo_rele(struct foo *fp)
    {
        pthread_mutex_lock(&fp->f_lock);
        if(--fp->f_count==0)
        {
            pthread_mutex_unlock(&fp->f_lock);
            pthread_mutex_destroy(&fp->f_lock);
            free(fp);
        }
        else
        {
            pthread_mutex_unlock(&fp->f_lock);
        }
    }

    读写锁

    读写锁有三种状态,加读锁,加写锁,不加锁,当位于写锁时,所有企图对读写锁加锁(无论时加读锁还是写锁)的线程都会阻塞,当位于加读锁时,所有试图对其加读锁的线程可以继续运行,但是加写锁的线程会阻塞。当读写锁位于读状态时,如果有一线程试图对其加写锁,那么读写锁通常会阻塞随后的加读锁请求,这样可以避免读模式锁长期占用,而写模式锁请求得不到满足。

    数据类型  pthread_rwlock_t

    #include <pthread.h>

    int pthread_rwclock_init(pthread_rwlock_t *restrict rwlock,const pthread_relockattr_t *restrict attr);   //初始化一个读写锁,要先分配内存。

    int pthread_rwclock_destroy(pthread_rwlock_t *rwlock)    //销毁锁   。2个函数成功返回0

    int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);   //加读锁

    int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock); //加写锁

    int pthread_rwlock_unlock(pthread_rwlock_t *rwlock); //解锁 若成功都返回0

    int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock);

    int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock);  //成功返回0

    条件变量

    如果说互斥锁用于同步线程对共享数据的访问,那么条件变量就是用于同步共享数据的值。

    #include <pthread.h>

    int pthread_cond_init(pthread_cond_t* cond,pthread_condattr_t* cond_attr);

    初始化一个条件量,若cond_attr为NULL,则以默认熟悉初始化,还可以pthread_cond_t cond=PTHREAD_COND_INITIALIZER;

    int pthread_cond_destroy(pthread_cond_t* cond);

    int pthread_cond_signal(pthread_cond_t* cond);

    唤醒一个等待该条件变量的线程

    int pthread_cond_broadcast(pthread_cond_t* cond);

    唤醒所有等待该条件变量的线程

    int pthread_cond_wait(pthread_cond_t* cond,pthread_mutex_t* mutex);

    等待目标条件变量,mutex用来保证该函数操作的原子性,在使用pthread_cond_wait函数之前,需保证对mutex加锁。该函数执行时,把调用线程加入条件变量的等待队列。调用完后需要对mutex解锁。

    上面的函数成功返回0,失败返回错误代码。

    下面是一个线程同步机制的包装类

    #include <exception>
    #include <pthread.h>
    #include <semphore.h>
    
    class sem{
    public:
        sem(unsigned int val=0){
            if(sem_init(&m_sem,0,val)!=0){
                throw std::exception();  //constructor don't have return val,if error,throw a exception
            }
        }
    
        ~sem(){
            sem_destroy(&m_sem);
        }
    
        //equal p operation
        bool wait(){
            return sem_wait(&m_sem)==0; 
        }
    
        //equal v operation
        bool post(){
            return sem_post(&m_sem)==0;
        }
    private:
        sem_t m_sem;
    
    
    };
    
    class locker{
    public:
        locker(){
            if(pthread_mutex_init(&m_mutex,NULL)!=0){
                throw std::exception();
            }
        }
    
        ~locker(){
            pthread_mutex_destroy(&m_mutex);
        }
    
        bool lock(){
            return pthread_mutex_lock(&m_mutex)==0;
        }
    
        bool unlock(){
            return pthread_mutex_unlock(&m_mutex)==0;
        }
    private:
        pthread_mutex_t m_mutex;
    };
    
    class cond{
    public:
        cond(){
            if(pthread_mutex_init(&m_mutex,NULL)!=0){
                throw std::exception();
            }
    
            if(pthread_cond_init(&m_cond,NULL)!=0){
                pthread_mutex_destroy(&m_mutex);
                throw std::exception();
            }
        }
    
        ~cond(){
            pthread_mutex_destroy(&m_mutex);
            pthread_cond_destroy(&m_cond);
        }
    
        bool wait(){
            int ret=0;
            pthread_mutex_lock(&m_mutex);
            ret=pthread_cond_wait(&m_cond,&m_mutex);
            pthread_mutex_unlock(&m_mutex);
            return ret==0;
        }
    
        bool signal(){
            return pthread_cond_signal(&m_cond)==0;
        }
    
    private:
        pthread_mutex_t m_mutex;
        pthread_cond_t m_cond;
    };
  • 相关阅读:
    ID,ClientID,UniqueID的区别
    Struct构造函数
    关于sizeof,typeof
    C#文件读写
    code1
    .NET中加密与解密QueryString的方法
    addEventListener和attachEvent的区别
    执行带参数的存储过程
    如何得到机器上装的Powershell的版本
    [Gradle] How to determine OS info
  • 原文地址:https://www.cnblogs.com/CodingUniversal/p/7413571.html
Copyright © 2020-2023  润新知