美文网首页
learn-pthread

learn-pthread

作者: my_passion | 来源:发表于2022-04-24 21:44 被阅读0次
Chapter 1: Getting started with pthreads 
    Examples 
        1   最小 "Hello World" with pthreads 
        2   传参 到 threads 
        3   从 thread 返回 结果 
    
Chapter 2: Conditional Variables
    介绍 
    注意 
    Examples 
        1   Producer / Consumer 
        
Chapter 3: Race condition in pthreads
    介绍 
    Examples 
        1   Consider will have two threads T1 and T2
// ===

Chapter 1: Getting started(开始) with pthreads 
    Examples 
        1   最小 "Hello World" with pthreads 
            
            // hello.c
            /* compile: $ gcc -pthread -o hello hello.c */
            #include <pthread.h>
            #include <stdio.h>
            #include <string.h>

            /*  thread function must have the same signature:
                    [1] para    : void*  
                    [2] returns : void* 
            */
            void *threadFunction(void *arg)
            {
                printf("Hello, World!\n"); /*   printf(): thread-safe as of C11 */
                
                return 0;
            }

            int main(void)
            {
                pthread_t thread;
                
                /* creates new thread: 
                    1] default attributes   
                    2] NULL passed as the argument to start routine
                */
                int createerror = pthread_create(&thread, NULL, threadFunction, NULL);
                
                if (!createerror) /* 0: success */
                {
                    pthread_join(thread, NULL); /* wait until the created thread terminates */
                    return 0;
                }
                
                /*  stderr:  [1] error info output to screen, whether or not relocate( hello > error.txt)
                    
                    char *strerror(int errnum) 
                        [1] searches internal array for the error number errnum
                        [2] returns a pointer to it's error message string
                */  
                fprintf(stderr, "%s\n", strerror(createerror) ); 
                
                return 1;
            }

            $ gcc -pthread -o a hello.c
            & ./a
            
            // print
            hello
            
        2   传参 到 threads
        
            // passArgsToThread.c
            #include <stdio.h>
            #include <pthread.h>

            void *thread_func(void *arg)
            {
                printf("I am thread #%d\n", *(int *)arg);
                return NULL;
            }

            int main(int argc, char *argv[])
            {
                 pthread_t t1, t2;
                 int i = 1;
                 int j = 2;
                 
                 /* 2 threads execute function "thread_func()" in their own contexts */
                 pthread_create(&t1, NULL, &thread_func, &i);
                 pthread_create(&t2, NULL, &thread_func, &j);
                 
                 pthread_join(t1, NULL);
                 pthread_join(t2, NULL);
                 printf("In main thread\n");
                 
                 return 0;
            }
            
            $ gcc -pthread -o a passArgsToThread.c
            & ./a
            
            // print
            I am thread #1
            I am thread #2
            In main thread

        3   从 thread 返回 结果 
        
            A ptr to concrete data type, 被转换 为 void *, 可用于 
                1] 传递值到 thread functon
                2] 从 thread function 返回结果 
            
            (1) thread 内 malloc, return heap memory's ptr, join 中 取 
            
            (2) argument struct 中 space 也可 用于 return results
            
            (3) ptr to shared data 可被 传给线程, results stored there

            // returnResultFromThread.c
            // way1
            #include <stdio.h>
            #include <stdlib.h>
            #include <pthread.h>

            struct thread_args
            {
                int a;
                double b;
            };
            struct thread_result
            {
                long x;
                double y;
            };

            void *thread_func(void *args_void)
            {
                // (2) para: void* -> ptr, 不用显式强转
                struct thread_args *args = args_void;
                
                /* (3) Note1: thread 不能 return ptr to it's local variable */
                struct thread_result *res = malloc(sizeof *res);
                
                res->x = 10 + args->a;
                res->y = args->a * args->b;
                
                return res;
            }

            int main()
            {
                pthread_t thread;
                
                struct thread_args in = { .a = 10, .b = 3.141592653 };
                
                void *out_void;
                struct thread_result *out;
                
                // (1) arg: ptr -> void* 
                pthread_create(&thread, NULL, thread_func, &in);
                
                // (4) Note2:   result: void* 的 地址 放 join
                pthread_join(thread, &out_void);
                
                // (5) result: void* -> ptr
                out = out_void;
                
                printf("out -> x = %ld\tout -> b = %f\n", out->x, out->y);
                
                // (6) free memory malloced within thread
                free(out);
                
                return 0;
            }   
                
            $ gcc -pthread -o a returnResultFromThread.c
            $ ./a
            out -> x = 20   out -> b = 31.415927

Chapter 2: Conditional Variables

    介绍 
        cv 适用场景: 希望 a thread 等待 another thread 中 发生某事 
        
        生产者(>=1) /消费者(=1) 模型
            cv 可用于 signal(向...发出信号) 消费者线程 new data is available(新数据可用)

    注意 
        通常过程 
            
            wait on cv 总是 
                与 mutex 耦合
                与 "正常" state variable 耦合( queue.empty() )

        对 signalling thread
            1   Lock mutex      // ===
            
            2   Update any data and state variables
            3   Signal cv
            
            4   Unlock mutex    // ===
        
        对 waiting thread
            1   Lock mutex                      // ===
            
            2   while loop on state variable, when data is not ready        
            3   within while loop, wait on cv   // ===
            
            // Note: cv.wait call 
            //          unlocks mutex when called, 
            //          relocks it before returning!
            4   Do something with the data
            
            5   Unlock the mutex and repeat     // ===
                
    Examples 
        1   Producer / Consumer 
        
        // cv.c
        /*
            lock: 保护 queue 上 并发操作 的 正确
            
                lock 保护范围
                    对 生成者:  push()
                    对 消费值:  front() + pop()
                    
                lock 不保护的范围 
                    对 生成者:  准备好 要 push 到 queue 的 data 前
                    对 消费值:  从 queue 取出/front() + 删除/pop() data 后 的 数据处理 
        */

        pthread_mutex_t queueMutex;
        pthread_cond_t queueEmptyCv;
        Queue queue;

        void Initialize() 
        {
            //Initialize the mutex and the condition variable
            pthread_mutex_init(&queueMutex, NULL);
            pthread_cond_init(&queueEmptyCv, NULL);
        }

        void Producer() 
        {
            // Note: get new data, 不必 within lock
            Data *newData = MakeNewData();      // (0)
            
            // Lock queue mutex: make sure that adding data to queue happens correctly
            pthread_mutex_lock(&queueMutex);    // === lock
            
            // Push new data to queue
            queue.push(newData);                // (1) push
            
            // Signal cv that new data is available in the queue
            pthread_cond_signal(&queueEmptyCv); // (2) signal
            
            // Done, unlock the mutex
            pthread_mutex_unlock(&queueMutex);  // === unlock
        }

        void Consumer() 
        {
            //Run the consumer loop
            while(1) 
            {
                
                pthread_mutex_lock(&queueMutex); // === 
                
                while( queue.empty() ) 
                {
                    // - wait for cv to be signalled
                    // Note: cv.wait call 
                    //          unlocks mutex when called, 
                    //          relocks it before returning!
                    pthread_cond_wait(&queueEmptyCv, &queueMutex); // === (1) cv.wait

                }
                
                // now, there must be new data in the queue - get it,
                Data *newData = queue.front();  // (2)
                
                // remove it from the queue
                queue.pop();                    // (3)
                
                // unlock the mutex
                pthread_mutex_unlock(&queueMutex); // ===
                
                // process the new data
                ProcessData(newData);           // (4)
            }
        }
        
Chapter 3: Race condition in pthreads

    介绍 
        Note: 若 所有线程 只是 read variable/resource/memory 位置(location), 
            
                    Race Condition 不会发生

    Examples 
        1   Consider will have two threads T1 and T2
        
            // raceConditionProblem.c
            #include <stdio.h>
            #include <pthread.h>

            int x= 0; // shared data(variable)

            void* fun(void* in)
            {
                int i;
                for ( i = 0; i < 10000000; i++ )
                    x++;
            }

            int main()
            {
                 pthread_t t1, t2;
                 printf("Point 1 >> X is: %d\n", x);
                 
                 pthread_create(&t1, NULL, fun, NULL);
                 pthread_create(&t2, NULL, fun, NULL);
                 
                 pthread_join(t1, NULL);
                 pthread_join(t2, NULL);
                 
                 printf("Point 2 >> X is: %d\n", x);
                 
                 return 0;
            }

            // raceConditionSolved.c
            #include <stdio.h>
            #include <pthread.h>

            int x= 0;
            pthread_mutex_t test_mutex; // Create mutex: shared mutex 

            void* fun(void* in)
            {
                int i;
                for ( i = 0; i < 10000000; i++ )
                {

                    pthread_mutex_lock(&test_mutex);    // === lock
                    
                    x++;
                
                    pthread_mutex_unlock(&test_mutex);  // === unlock
                }
            }

            int main()
            {
                pthread_t t1, t2;
                
                printf("Point 1 >> X is: %d\n", x);
                
                //Initlize mutex
                pthread_mutex_init(&test_mutex, NULL); // === init
                
                pthread_create(&t1, NULL, fun, NULL);
                pthread_create(&t2, NULL, fun, NULL);
                
                pthread_join(t1, NULL);
                pthread_join(t2, NULL);
                
                //Destroy mutex after use
                pthread_mutex_destroy(&test_mutex);   // === destroy
                
                printf("Point 2 >> X is: %d\n", x);
                
                return 0;
            }


            // print 
            Point 1 >> X is: 0
            Point 2 >> X is: 20000000

相关文章

网友评论

      本文标题:learn-pthread

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