美文网首页
多线程锁

多线程锁

作者: 7ee64cf5edb2 | 来源:发表于2019-10-22 19:20 被阅读0次
    1. 背景知识:
    多线程中经常需要使用到锁(pthread_mutex_t)来完成多个线程之间的某些同步操作
    • 互斥锁:为了使不同线程互斥的使用某个资源
        ○ 锁的创建:pthread_mutex_init
            § pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
            § int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t * attr);
        ○ 锁的属性:
            pthread_mutexattr_init(pthread_mutexattr_t *mattr)
            pthread_mutexattr_settype(pthread_mutexattr_t *attr , int type)
            pthread_mutexattr_gettype(pthread_mutexattr_t *attr , int *type)
            § 普通锁:PTHREAD_MUTEX_TIMED_NP(当一个线程加锁以后,其余请求锁的线程将形成一个等待队列,并在解锁后按优先级获得锁。这种锁策略保证了资源分配的公平性)
            § 嵌套锁:PTHREAD_MUTEX_RECURSIVE_NP(允许同一个线程对同一个锁成功获得多次,并通过多次unlock解锁。如果是不同线程请求,则在加锁线程解锁时重新竞争)
            § 检错锁:PTHREAD_MUTEX_ERRORCHECK_NP(如果同一个线程请求同一个锁,则返回EDEADLK,否则与PTHREAD_MUTEX_TIMED_NP类型动作相同。这样就保证当不允许多次加锁时不会出现最简单情况下的死锁)
            § 适应锁:PTHREAD_MUTEX_ADAPTIVE_NP(动作最简单的锁类型,仅等待解锁后重新竞争)
        ○ 锁的释放:pthread_mutex_destory
        ○ 锁操作:
            § 加锁:int pthread_mutex_lock(pthread_mutex_t *mutex)
            § 解锁:int pthread_mutex_unlock(pthread_mutex_t *mutex)
            § 测试加锁:int pthread_mutex_trylock(pthread_mutex_t *mutex)
    • 条件锁:为了保证不同线程之间有顺序(通过条件控制)地完成某个流程
        ○ 等待方式:
            § 无条件等待:pthread_cond_wait()
            § 计时等待:pthread_cond_timedwait()
        ○ 激活条件:
            §  int pthread_cond_signal(pthread_cond_t *cond); 激活一个等待该条件的线程,存在多个等待线程时按入队顺序激活其中一个
            § int pthread_cond_broadcast(pthread_cond_t *cond);  激活所有等待线程
    

    互斥锁:

    #include <pthread.h>
    #include <stdio.h>
     
    pthread_mutex_t mutex ;
    void *print_msg(void *arg){
            int i=0;
            pthread_mutex_lock(&mutex);
            for(i=0;i<15;i++){
                    printf("output : %d\n",i);
                    usleep(100);
            }
            pthread_mutex_unlock(&mutex);
    }
    int main(int argc,char** argv){
            pthread_t id1;
            pthread_t id2;
            pthread_mutex_init(&mutex,NULL);
            pthread_create(&id1,NULL,print_msg,NULL);
            pthread_create(&id2,NULL,print_msg,NULL);
            pthread_join(id1,NULL);
            pthread_join(id2,NULL);
            pthread_mutex_destroy(&mutex);
            return 1;
    }
    

    条件锁:

    //一个生产者消费者模型
    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
    #include <pthread.h>
    #include <unistd.h>
    
    typedef struct node
    {
        int num;
        struct node *next;
    } node_t;
    
    typedef node_t *list_t;
    list_t head = NULL;
    pthread_mutex_t mutex =
        PTHREAD_MUTEX_INITIALIZER;
    pthread_cond_t cond =
        PTHREAD_COND_INITIALIZER;
    
    //消费者线程
    void *consume(void *arg)
    {
        node_t *tmp;
        while (1)
        {
            //加锁
            pthread_mutex_lock(&mutex); //对临界变量加锁
            if (head == NULL)           //如果头部指向空,等待
                pthread_cond_wait(&cond, &mutex);
            tmp = head;        //将要删除的节点赋值给中间值,然后头指针指向下一个
            head = head->next; //
            //解锁
            pthread_mutex_unlock(&mutex);
            //消费tmp节点
            printf("consum:%d\n", tmp->num);
            free(tmp);
            tmp = NULL;
            sleep(rand() % 5);
        }
    }
    
    //生产者线程
    void *product(void *arg)
    { //函数的格式void *(*start_routine) (void *),返回值是指针,参数也是
        node_t *n;
        while (1)
        {
            //生产一个新的节点
            n = (node_t *)malloc(sizeof(node_t));
            n->num = rand() % 1000 + 1;
            printf("p:%d\n", n->num);
            //加锁
            pthread_mutex_lock(&mutex);
            //将新节点放入到链表的头部
            n->next = head;
            head = n;
            //解锁
            pthread_mutex_unlock(&mutex);
            //通知消费者
            pthread_cond_signal(&cond);
            sleep(rand() % 5);
        }
    }
    int main(void)
    {
        pthread_t pid, cid;
        //设置随机数的种子
        srand(time(NULL));
        //创建两个线程,用于生产者和消费者
        pthread_create(&pid, NULL, product, NULL); //创建线程后即执行该线程
        pthread_create(&cid, NULL, consume, NULL); //参数含义是(存放ID的缓存区,NULL缺省属性,线程的执行函数,函数的唯一参数)
        //等待线程的汇合
        pthread_join(pid, NULL);
        pthread_join(cid, NULL);
        //销毁mutex锁
        pthread_mutex_destroy(&mutex);
        pthread_cond_destroy(&cond);
        return 0;
    }
    

    相关文章

      网友评论

          本文标题:多线程锁

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