zoukankan      html  css  js  c++  java
  • Linux 线程同步的三种方法(互斥锁、条件变量、信号量)

    互斥锁

     1 #include <cstdio>
     2 
     3 #include <cstdlib>
     4 
     5 #include <unistd.h>
     6 
     7 #include <pthread.h>
     8 
     9 #include "iostream"
    10 
    11 using namespace std;
    12 
    13 pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
    14 
    15 int tmp;
    16 
    17 void* thread(void *arg)
    18 
    19 {
    20 
    21     cout << "thread id is " << pthread_self() << endl;
    22 
    23     pthread_mutex_lock(&mutex);
    24 
    25     tmp = 12;
    26 
    27     cout << "Now a is " << tmp << endl;
    28 
    29     pthread_mutex_unlock(&mutex);
    30 
    31     return NULL;
    32 
    33 }
    34 
    35 int main()
    36 
    37 {
    38 
    39     pthread_t id;
    40 
    41     cout << "main thread id is " << pthread_self() << endl;
    42 
    43     tmp = 3;
    44 
    45     cout << "In main func tmp = " << tmp << endl;
    46 
    47     if (!pthread_create(&id, NULL, thread, NULL))
    48 
    49     {
    50 
    51         cout << "Create thread success!" << endl;
    52 
    53     }
    54 
    55     else
    56 
    57     {
    58 
    59         cout << "Create thread failed!" << endl;
    60 
    61     }
    62 
    63     pthread_join(id, NULL);
    64 
    65     pthread_mutex_destroy(&mutex);
    66 
    67     return 0;
    68 
    69 }
    70 
    71 //编译:g++ -o thread testthread.cpp -lpthread

    条件变量

    #include <stdio.h>
    
    #include <pthread.h>
    
    #include "stdlib.h"
    
    #include "unistd.h"
    
    pthread_mutex_t mutex;
    
    pthread_cond_t cond;
    
    void hander(void *arg)
    
    {
    
        free(arg);
    
        (void)pthread_mutex_unlock(&mutex);
    
    }
    
    void *thread1(void *arg)
    
    {
    
        pthread_cleanup_push(hander, &mutex);
    
        while(1)
    
        {
    
            printf("thread1 is running
    ");
    
            pthread_mutex_lock(&mutex);
    
            pthread_cond_wait(&cond, &mutex);
    
            printf("thread1 applied the condition
    ");
    
            pthread_mutex_unlock(&mutex);
    
            sleep(4);
    
        }
    
        pthread_cleanup_pop(0);
    
    }
    
    void *thread2(void *arg)
    
    {
    
        while(1)
    
        {
    
            printf("thread2 is running
    ");
    
            pthread_mutex_lock(&mutex);
    
            pthread_cond_wait(&cond, &mutex);
    
            printf("thread2 applied the condition
    ");
    
            pthread_mutex_unlock(&mutex);
    
            sleep(1);
    
        }
    
    }
    
    int main()
    
    {
    
        pthread_t thid1,thid2;
    
        printf("condition variable study!
    ");
    
        pthread_mutex_init(&mutex, NULL);
    
        pthread_cond_init(&cond, NULL);
    
        pthread_create(&thid1, NULL, thread1, NULL);
    
        pthread_create(&thid2, NULL, thread2, NULL);
    
        sleep(1);
    
        do
    
        {
    
            pthread_cond_signal(&cond);
    
        }while(1);
    
        sleep(20);
    
        pthread_exit(0);
    
        return 0;
    
    }
    #include <pthread.h>
    
    #include <unistd.h>
    
    #include "stdio.h"
    
    #include "stdlib.h"
    
    static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
    
    static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
    
    struct node
    
    {
    
        int n_number;
    
        struct node *n_next;
    
    }*head = NULL;
    
     
    
    static void cleanup_handler(void *arg)
    
    {
    
        printf("Cleanup handler of second thread./n");
    
        free(arg);
    
        (void)pthread_mutex_unlock(&mtx);
    
    }
    
    static void *thread_func(void *arg)
    
    {
    
        struct node *p = NULL;
    
        pthread_cleanup_push(cleanup_handler, p);
    
        while (1)
    
        {
    
            //这个mutex主要是用来保证pthread_cond_wait的并发性
    
            pthread_mutex_lock(&mtx);
    
            while (head == NULL)
    
            {
    
                //这个while要特别说明一下,单个pthread_cond_wait功能很完善,为何
    
                //这里要有一个while (head == NULL)呢?因为pthread_cond_wait里的线
    
                //程可能会被意外唤醒,如果这个时候head != NULL,则不是我们想要的情况。
    
                //这个时候,应该让线程继续进入pthread_cond_wait
    
                // pthread_cond_wait会先解除之前的pthread_mutex_lock锁定的mtx,
    
                //然后阻塞在等待对列里休眠,直到再次被唤醒(大多数情况下是等待的条件成立
    
                //而被唤醒,唤醒后,该进程会先锁定先pthread_mutex_lock(&mtx);,再读取资源
    
                //用这个流程是比较清楚的
    
                pthread_cond_wait(&cond, &mtx);
    
                p = head;
    
                head = head->n_next;
    
                printf("Got %d from front of queue/n", p->n_number);
    
                free(p);
    
            }
    
            pthread_mutex_unlock(&mtx); //临界区数据操作完毕,释放互斥锁
    
        }
    
        pthread_cleanup_pop(0);
    
        return 0;
    
    }
    
    int main(void)
    
    {
    
        pthread_t tid;
    
        int i;
    
        struct node *p;
    
        //子线程会一直等待资源,类似生产者和消费者,但是这里的消费者可以是多个消费者,而
    
        //不仅仅支持普通的单个消费者,这个模型虽然简单,但是很强大
    
        pthread_create(&tid, NULL, thread_func, NULL);
    
        sleep(1);
    
        for (i = 0; i < 10; i++)
    
        {
    
            p = (struct node*)malloc(sizeof(struct node));
    
            p->n_number = i;
    
            pthread_mutex_lock(&mtx); //需要操作head这个临界资源,先加锁,
    
            p->n_next = head;
    
            head = p;
    
            pthread_cond_signal(&cond);
    
            pthread_mutex_unlock(&mtx); //解锁
    
            sleep(1);
    
        }
    
        printf("thread 1 wanna end the line.So cancel thread 2./n");
    
        //关于pthread_cancel,有一点额外的说明,它是从外部终止子线程,子线程会在最近的取消点,退出
    
        //线程,而在我们的代码里,最近的取消点肯定就是pthread_cond_wait()了。
    
        pthread_cancel(tid);
    
        pthread_join(tid, NULL);
    
        printf("All done -- exiting/n");
    
        return 0;
    
    }

    信号量

    #include <stdlib.h>
    
    #include <stdio.h>
    
    #include <unistd.h>
    
    #include <pthread.h>
    
    #include <semaphore.h>
    
    #include <errno.h>
    
    #define return_if_fail(p) if((p) == 0){printf ("[%s]:func error!/n", __func__);return;}
    
    typedef struct _PrivInfo
    
    {
    
        sem_t s1;
    
        sem_t s2;
    
        time_t end_time;
    
    }PrivInfo;
    
     
    
    static void info_init (PrivInfo* thiz);
    
    static void info_destroy (PrivInfo* thiz);
    
    static void* pthread_func_1 (PrivInfo* thiz);
    
    static void* pthread_func_2 (PrivInfo* thiz);
    
     
    
    int main (int argc, char** argv)
    
    {
    
        pthread_t pt_1 = 0;
    
        pthread_t pt_2 = 0;
    
        int ret = 0;
    
        PrivInfo* thiz = NULL;
    
        thiz = (PrivInfo* )malloc (sizeof (PrivInfo));
    
        if (thiz == NULL)
    
        {
    
            printf ("[%s]: Failed to malloc priv./n");
    
            return -1;
    
        }
    
        info_init (thiz);
    
        ret = pthread_create (&pt_1, NULL, (void*)pthread_func_1, thiz);
    
        if (ret != 0)
    
        {
    
            perror ("pthread_1_create:");
    
        }
    
        ret = pthread_create (&pt_2, NULL, (void*)pthread_func_2, thiz);
    
        if (ret != 0)
    
        {
    
            perror ("pthread_2_create:");
    
        }
    
        pthread_join (pt_1, NULL);
    
        pthread_join (pt_2, NULL);
    
        info_destroy (thiz);
    
        return 0;
    
    }
    
    static void info_init (PrivInfo* thiz)
    
    {
    
        return_if_fail (thiz != NULL);
    
        thiz->end_time = time(NULL) + 10;
    
        sem_init (&thiz->s1, 0, 1);
    
        sem_init (&thiz->s2, 0, 0);
    
        return;
    
    }
    
    static void info_destroy (PrivInfo* thiz)
    
    {
    
        return_if_fail (thiz != NULL);
    
        sem_destroy (&thiz->s1);
    
        sem_destroy (&thiz->s2);
    
        free (thiz);
    
        thiz = NULL;
    
        return;
    
    }
    
    static void* pthread_func_1 (PrivInfo* thiz)
    
    {
    
        return_if_fail(thiz != NULL);
    
        while (time(NULL) < thiz->end_time)
    
        {
    
            sem_wait (&thiz->s2);
    
            printf ("pthread1: pthread1 get the lock./n");
    
            sem_post (&thiz->s1);
    
            printf ("pthread1: pthread1 unlock/n");
    
            sleep (1);
    
        }
    
        return;
    
    }
    
    static void* pthread_func_2 (PrivInfo* thiz)
    
    {
    
        return_if_fail (thiz != NULL);
    
        while (time (NULL) < thiz->end_time)
    
        {
    
            sem_wait (&thiz->s1);
    
            printf ("pthread2: pthread2 get the unlock./n");
    
            sem_post (&thiz->s2);
    
            printf ("pthread2: pthread2 unlock./n");
    
            sleep (1);
    
        }
    
        return;
    
    }

     

    总结:

    互斥锁是是访问共享变量的,防止多线程同时写出现脏数据。

    信号量是用来线程同步的,可两线程双向互相通知,也可单向通知。

    条件变量是信号量的一种封装,用于线程单向等待另一个线程的通知,也可先后多个线程等待同一个条件变量的唤醒。

    参考资料:https://blog.csdn.net/zsf8701/article/details/7844316

  • 相关阅读:
    【转】浅谈一个网页打开的全过程(涉及DNS、CDN、Nginx负载均衡等)
    【转】1.2 CDN的基本工作过程
    【转】 最新版chrome谷歌浏览器Ajax跨域调试问题
    【转】网段,子网掩码,网络标识,IP划分
    【转】默认网关有什么用?我应当怎么填写默认网关和DNS呢
    【转】DHCP工作过程详解
    【转】WINS服务器与DNS服务器有什么区别?
    46. Permutations 排列数
    30. Substring with Concatenation of All Words
    29. Divide Two Integers
  • 原文地址:https://www.cnblogs.com/heluan/p/10054756.html
Copyright © 2011-2022 走看看