美文网首页
APUE//线程同步

APUE//线程同步

作者: ustclcl | 来源:发表于2019-03-24 22:24 被阅读0次

互斥量mutex

#include <pthread,h>
int pthread_mutex_init(pthread_mutex_t *restrict mutex,
                                      const pthread_mutexattr_t *restrict attr);

int pthread_mutex_destroy(pthread_mutex_t *mutex);

int pthread_mutex_lock(pthread_mutex_t *mutex);
//对互斥量加锁,如果已经加锁,线程阻塞直至被解锁
int pthread_mutex_trylock(pthread_mutex_t *mutex);
//如果已经加锁,不会阻塞,而是返回EBUSY
int pthread_mutex_unlock(pthread_mutex_t *mutex);

下面的例子演示对一个对象进行引用计数。引用计数是受互斥量保护的,每回hold对象时,加锁,引用计数加一;release时,解锁,引用计数减一。例外情况是在初始化时,对象刚被创造,不需要加锁。以及对象最后一个引用释放时同时释放空间。

// APUE 11-10                                              
//  use mutex to protect data                              
//  lcl 20190324                                           
//                                                         
#include "../myapue.h"                                     
#include <pthread.h>                                       
                                                           
struct foo {                                               
    int             f_count;                               
    pthread_mutex_t f_lock;                                
    int             f_id;                                  
    /* more stuff here */                                  
};                                                         
                                                           
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_destory(&fp->f_lock);                
        free(fp);                                          
    }                                                      
    else                                                   
     {                                                             
         pthread_mutex_unlock(&fp->f_lock);                        
     }                                                             
 }                                                                 
                                                                   

避免死锁,使用两个互斥锁时,需要操作时指定加锁顺序,否则可能造成两个资源相互持有对方需要的锁,一直处于阻塞状态。下例中,既有保护对象的锁f_lock,也有对象所在的全局哈希表的锁hashlock,当同时使用两个锁时,每次操作都按照先锁hashlock再锁f_lock。

// APUE 11-11                                                          
//  use two mutex to protect struct and hash                           
//  lcl 20190324                                                       
//                                                                     
#include "../myapue.h"                                                 
#include <pthread.h>                                                   
                                                                       
#define NHASH 29                                                       
#define HASH(id) (((unsigned long)id)%NHASH)                           
                                                                       
struct foo *fh[NHASH];                                                 
                                                                       
pthread_mutex_t hashlock = PTHREAD_MUTEX_INITIALIZER;                  
                                                                       
struct foo {                                                           
    int             f_count;                                           
    pthread_mutex_t f_lock;                                            
    int             f_id;                                              
    /* more stuff here */                                              
    struct foo      *f_next;                                           
};                                                                     
                                                                       
struct foo* foo_alloc(int id)                                          
{                                                                      
    struct foo * fp;                                                   
    int  idx;                                                          
                                                                       
    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);                                              
        }                                                              
        idx = HASH(id);                                                
        pthread_mutex_lock(&hashlock);                                 
        fp->f_next = fh[idx];                                          
        fh[idx] = fp;                                                  
        pthread_mutex_lock(&fp->f_lock);                               
        pthread_mutex_unlock(&hashlock);                               
        /* ... */                                                      
        pthread_mutex_unlock(&fp->f_lock);                             
    }                                                                  
    return(fp);                                                        
}                                                                      

 void foo_hold(struct foo *fp)                                           
 {                                                                       
     pthread_mutex_lock(&fp->f_lock);                                    
     fp->f_count++;                                                      
     pthread_mutex_unlock(&fp->f_lock);                                  
 }                                                                       
                                                                         
 struct foo_find(int id)                                                 
 {                                                                       
     struct foo *fp;                                                     
     pthread_mutex_lock(&hashlock);                                      
     for (fp = fh[HASH(id)]; fp != NULL; fp = fp->f_next){               
         if (fp->f_id == id){                                            
             foo_hold(fp);                                               
             break;                                                      
         }                                                               
     }                                                                   
     pthread_mutex_unlock(&hashlock);                                    
     return(fp);                                                         
 }                                                                       
                                                                         
 void foo_rele(struct foo * fp)                                          
 {                                                                       
     struct foo *fp;                                                     
     int idx;                                                            
                                                                         
     pthread_mutex_lock(&fp->f_lock);                                    
     if (fp->f_count == 1) {                                             
         pthread_mutex_unlock(&fp->f_lock);                              
         pthread_mutex_lock(&hashlock);                                  
         pthread_mutex_lock(&fp->f_lock);                                
         if (fp->f_count != 1)                                           
         {                                                               
             fp->f_count--;                                              
             pthread_mutex_unlock(&fp->f_lock);                          
             pthread_mutex_unlock(&hashlock);                            
             return;                                                     
         }                                                               
         idx = HASH(fp->f_id);                                           
         tfp = fh[idx];                                                  
         if(tfp == fp){                                                  
             fh[idx] = fp ->f_next;                                      
         }                                                               
         else                                                            
         {                                                               
             while(tfp->next != fp)                               
             {                                                    
                 tfp = tfp->next;                                 
             }                                                    
             tfp->next = fp->next;                                
         }                                                        
         pthread_mutex_unlock(&hashlock);                         
         pthread_mutex_unlock(&fp->f_lock);                       
         pthread_mutex_destory(&fp->f_lock);                      
         free(fp);                                                
     }                                                            
     else                                                         
     {                                                            
         fp->f_count--;                                           
         pthread_mutex_unlock(fp->f_lock);                        
     }                                                            
 }                                                                
                                                                                                                                         

这样做的负担显而易见,尤其是release时,因为最后一个引用release时,需要删除,又需要操作哈希表,按照加锁顺序的要求,此时要先释放f_lock,再锁hashlock,再锁f_lock,而再这个过程中,其他线程可能又占用了该资源,需要重新检查计数。。

若只使用hashlock来管理,则会变得简单。

void foo_hold(struct foo *fp)                              
{                                                          
    pthread_mutex_lock(&hashlock);                       
    fp->f_count++;                                         
    pthread_mutex_unlock(&hashlock);                     
}                                                          
                                                           
void foo_rele(struct foo * fp)                             
{                                                          
    pthread_mutex_lock(&hashlock);                       
    if (--fp->f_count == 0) {                              
        pthread_mutex_unlock(&hashlock);                 
        pthread_mutex_destory(&hashlock);                
        free(fp);                                          
    }                                                      
    else                                                   
     {                                                             
         pthread_mutex_unlock(&hashlock);                        
     }                                                             
 } 

但是这样的锁太粗,容易造成多个线程等待同一把锁,影响性能。所以需要进行性能和复杂的平衡。

相关文章

  • APUE//线程同步

    互斥量mutex 下面的例子演示对一个对象进行引用计数。引用计数是受互斥量保护的,每回hold对象时,加锁,引用计...

  • APUE//线程同步2

    时间锁 愿意等待timespec描述的时间,达到时间返回错误码ETIMEOUT一个例子 运行结果: 读写锁,三种状...

  • APUE//线程同步3

    使用条件变量进行线程同步 barrier,屏障

  • 【APUE】线程

  • APUE线程

    十一章 线程 多线程可以实现在某一个时刻能够做不止一件事,每个线程处理各自独立的任务 好处如下通过为每种事件类型分...

  • OpenMP多线程——Parallel for

    多线程——线程同步 数据竞争问题 线程互斥同步——critical 线程互斥同步——atmoic 线程互斥同步——...

  • iOS线程同步

    iOS线程同步 iOS线程同步

  • 线程的基本语法

    线程同步[解决线程安全问题] 解决线程安全问题 线程同步方式一:同步代码 语法基本 synchronized (同...

  • iOS多线程小结

    同步异步串行并行 同步串行:不开启线程 同步并行:不开启线程 异步串行:最多开启一个线程 异步并行:开启线程 同步...

  • python防遗忘复习练手之:多线程

    多线程 线程同步

网友评论

      本文标题:APUE//线程同步

      本文链接:https://www.haomeiwen.com/subject/tchpvqtx.html