線程同步生產者和消費者c和java不同實現

javac 分別實現下消費者 生產者模式,更好的理解如何通過互斥鎖條件變量來保證資源同步


java

    package com.toc;

    import java.util.LinkedList;
    import java.util.concurrent.TimeUnit;

    public class MutexCond {

        private static LinkedList<Integer> list = new LinkedList<Integer>();

        public static void main(String[] args) throws InterruptedException {
            Thread pThread = new Thread(new Producer(list));
            Thread cThread = new Thread(new Consumer(list));
            pThread.start();
            cThread.start();
            pThread.join();
            cThread.join();
        }

        public static class Producer implements Runnable{

            private LinkedList<Integer> pList;
            public Producer(LinkedList<Integer> list) {
                this.pList = list;
            }
            int capacity = 10 ;
            int value = 0 ;
            @Override
            public void run() {
                while(true){
                    // 上鎖的對象pList
                    synchronized (pList) {
                        if (pList.size() == capacity) {
                            try {
                                // 就要由上鎖的對象wait,從而釋放鎖,如果是this,可以省略不寫
                                // 容易出錯
                                pList.wait();
                            } catch (InterruptedException e) {
                            }
                        }
                        System.out.println("Producer produced + " + value);
                        value ++ ;
                        pList.add(value);
                        // 上鎖對象notify
                        pList.notify();
                        try {
                            TimeUnit.SECONDS.sleep(1);
                        } catch (InterruptedException e) {
                        }
                    }
                }
            }

        }

        public static class Consumer implements Runnable{
            private LinkedList<Integer> cList;
            public Consumer(LinkedList<Integer> list) {
                this.cList = list;
            }

            @Override
            public void run() {
                while(true){
                    synchronized (cList) {
                        if(list.size() == 0){
                            try {
                                cList.wait();
                            } catch (InterruptedException e) {
                            }
                        }
                        int val = cList.removeFirst();
                        System.out.println("Consumer consumed ----- " + val);
                        cList.notify();
                        try {
                            Thread.sleep(1000);
                        } catch (InterruptedException e) {
                        }
                    }
                }
            }
        }
    }

c

    // 生產者-消費者的例子,生產者生產一個結構體串在鏈表的表頭上,消費者從表頭取走結構體。

    #include <stdlib.h>
    #include <pthread.h>
    #include <stdio.h>

    struct msg {
        struct msg *next;
        int num;
    };

    struct msg *head;
    pthread_cond_t has_product = PTHREAD_COND_INITIALIZER;
    pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;

    void *consumer(void *p)
    {
        struct msg *mp;

        for (;;) {
            pthread_mutex_lock(&lock);
            while (head == NULL)
                pthread_cond_wait(&has_product, &lock);
            mp = head;
            head = mp->next;
            pthread_mutex_unlock(&lock);
            printf("Consume %d\n", mp->num);
            free(mp);
            sleep(rand() % 5);
        }
    }

    void *producer(void *p)
    {
        struct msg *mp;
        for (;;) {
            mp = malloc(sizeof(struct msg));
            pthread_mutex_lock(&lock);
            mp->next = head;
            mp->num = rand() % 1000;
            head = mp;
            printf("Produce %d\n", mp->num);
            pthread_mutex_unlock(&lock);
            pthread_cond_signal(&has_product);
            sleep(rand() % 5);
        }
    }

    int main(int argc, char *argv[]) 
    {
        pthread_t pid, cid;  

        srand(time(NULL));
        pthread_create(&pid, NULL, producer, NULL);
        pthread_create(&cid, NULL, consumer, NULL);
        pthread_join(pid, NULL);
        pthread_join(cid, NULL);
        return 0;
    }

總結

c

  • c在linux下是通過引入互斥鎖(Mutex,Mutual Exclusive Lock) 來實現線程之間的同步的。獲得鎖的線程可以完成“讀-修改-寫”的操作,然後釋放鎖給其它線程,沒有獲得鎖的線程只能等待而不能訪問共享數據,這樣“讀-修改-寫”三步操作組成一個原子操作,要麼都執行,要麼都不執行,不會執行到中間被打斷,也不會在其它處理器上並行做這個操作。

  • Mutex用pthread_mutex_t類型的變量表示,可以這樣初始化和銷燬:

    #include <pthread.h>

    int pthread_mutex_destroy(pthread_mutex_t *mutex);
    int pthread_mutex_init(pthread_mutex_t *restrict mutex,
           const pthread_mutexattr_t *restrict attr);
// 如果Mutex變量是靜態分配的(全局變量或static變量),也可以用宏定義PTHREAD_MUTEX_INITIALIZER來初始化,相當於用pthread_mutex_init初始化並且attr參數爲NULL
    pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
  • 返回值:成功返回0,失敗返回錯誤號。

  • 線程間的同步還有這樣一種情況:線程A需要等某個條件成立才能繼續往下執行,現在這個條件不成立,線程A就阻塞等待,而線程B在執行過程中使這個條件成立了,就喚醒線程A繼續執行。在pthread庫中通過條件變量(Condition Variable)來阻塞等待一個條件,或者喚醒等待這個條件的線程。Condition Variablepthread_cond_t類型的變量表示,可以這樣初始化和銷燬:

    #include <pthread.h>

    int pthread_cond_destroy(pthread_cond_t *cond);
    int pthread_cond_init(pthread_cond_t *restrict cond,
           const pthread_condattr_t *restrict attr);
    pthread_cond_t cond = PTHREAD_COND_INITIALIZER;

java

  • 在java中synchronized其實也是一種互斥鎖,而配合waitnotify notifyAll方法,同樣實現了條件變量,實現了線程的同步。

  • 有一點需要注意的是,加鎖的對象一定要明確,給誰加的鎖,必須由誰來waitnotify,否則會拋出監視對象不一致的異常。當加鎖對象是this時,wait和notify可以省略,但是一定要明確給誰加的。可以改動上面的例子,試着拋出monitor不一致的異常。


發佈了29 篇原創文章 · 獲贊 25 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章