Use mutexes, and condition variables The pthread_cond_wait () function

1. Linux "threads"

     There is a difference between processes and threads, but linux kernel only provides support for lightweight processes, unrealized threading model. Linux is a "multi-process single-threaded," the operating system . Linux itself is only the process of concept, and its so-called "thread" in the kernel is still nature of the process.

     As we all know, is the process of resource allocation units, multiple threads in the same process share the resources of the process (such as a global variable shared memory). Linux in the so-called "thread" is just clone was created when the resources of the parent process, so the clone out of the process performance of the "thread", which is sure to clarify. Therefore, Linux "thread" concept only in the case of playing the colon is the most accurate.

     Linux is currently the most popular thread mechanism LinuxThreads, is used by a thread - the process of "one on one" model, scheduling to the core, and in the user-level thread management mechanism to achieve, including signal processing, including. LinuxThreads by the Xavier Leroy ([email protected]) responsible for the development completed and binding in GLIBC issue, which implements a BiCapitalized for Linux, Posix 1003.1c "pthread" standard interface. Linuxthread can support multi-processor systems on the platform Intel, Alpha, MIPS and so on. 

POSIX 1003.1c prepared in accordance with standard procedures and Linuxthread library linked to support multi-threading on the Linux platform, the program needs to include the header file pthread h, use the command when compiling links: 
 

gcc -D -REENTRANT -lpthread xxx. c


-REENTRANT which makes macro-related library functions (such as stdio.h, errno.h in function) is reentrant and thread-safe (thread-safe), - lpthread means libpthread.a or libpthread next link library catalog .so file. Use Linuxthread library requires version 2.0 or later of the Linux kernel and the appropriate version of the C library (libc 5.2.18, libc 5.4.12, libc 6).

     2. "thread" control 

thread is created 

when the process is created, the system will create a main thread, but to create a new thread in the process, you can call pthread_create: 
 

pthread_create(pthread_t *thread, const pthread_attr_t *attr, void * 
(start_routine)(void*), void *arg);


start_routine for the new thread entry function, arg parameter is passed to the start_routine. 

Each thread has its own thread ID, in order to distinguish in the process. Return thread ID to create the caller's thread in the pthread_create call; one thread can also be used pthread_self after creating () call to get its own thread ID: 
 

pthread_self (void) ;


Thread exits 

thread exit strategy are threefold: 

(1) Upon completion of the implementation of implicit exit; 

(2) by the thread itself shows the call pthread_exit function exits; 
 

pthread_exit (void * retval) ;


(3) by another thread function terminates with pthread_cance: 
 

pthread_cance (pthread_t thread) ;


This function is called in a thread can be terminated by the specified parameters thread thread. 

If one thread to wait for another thread to terminate, you can use pthread_join function, that function does is to call pthread_join thread will be suspended until the thread ID for the thread to terminate the thread parameters: 
 

pthread_join (pthread_t thread, void** threadreturn);

3. Thread the communication 

thread mutex 

mutex means "exclusive", that is, two threads can not enter the exclusive protection code. Linux can be done by pthread_mutex_t defined mutex mutex operation of multi-threaded mechanism, the role of the mechanism is a need for mutually exclusive part, upon entering first get mutex, mutex if not, show mutual repellent portion is owned by other threads, thread blocking to obtain this case mutex until the thread owns the mutex operations is completed mutually exclusive portion. 

The following code to achieve the object of the shared global variable x to be protected by a mutex mutex is: 
 

int x; // global variables in the process of 
pthread_mutex_t mutex; 
pthread_mutex_init (& mutex, NULL); // initialize attributes by default mutex variable mutex 
pthread_mutex_lock (& mutex); // variable to the mutex lock 
... // operation of the variable x 
phtread_mutex_unlock (& mutex); // unlock a mutex variable


Thread Synchronization 

Synchronization thread is waiting for an event to occur. Only when waits event before continuing execution thread, or the thread hangs and give up the processor. When multiple threads collaboration, interaction tasks must be synchronized under certain conditions. 

Under Linux C language programming has a variety of thread synchronization mechanisms, the most typical is the condition variable (condition variable). pthread_cond_init used to create a condition variable, its function prototype is: 
 

pthread_cond_init (pthread_cond_t *cond, const pthread_condattr_t *attr);


pthread_cond_wait and pthread_cond_timedwait to wait for condition variable is set, it is worth noting that these two need to wait for a call already locked mutex mutex, which is to prevent the state before actually entering the waiting another thread is possible to set the condition variable and compete. Pthread_cond_wait function prototype is: 
 

pthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex);


pthread_cond_broadcast for setting a condition variable, even if the incident was, so the waiting thread that the event will no longer be blocked: 
 

pthread_cond_broadcast (pthread_cond_t *cond) ;


pthread_cond_signal is used to unblock a certain waiting threads: 
 

pthread_cond_signal (pthread_cond_t *cond) ;


pthread_cond_destroy the release of resources for a condition variable. 

The amount of signal is defined in the header file in the completed package semaphore.h mutex and condition variables, and access control mechanisms designed in a multithreaded program, the synchronization control access to resources, personnel provide easier programming call interface. 
 

sem_init(sem_t *sem, int pshared, unsigned int val);


This function initializes the value of a semaphore sem val, pshared parameter control is shared property, it indicates whether shared between processes. 
 

sem_wait (not sem_t *);


The function is called, if the sem-free state, the calling thread blocked waiting for the semaphore value increases sem (POST) becomes the signal state; sem if there is a state, the calling thread sequentially performed, but the value of the semaphore by one. 
 

sem_post (not sem_t *);


Calling the function, the value of the semaphore sem increases from no signal state to be signaled.

    

 

4. Examples 

Here we are still in the name of the producer / consumer issue as an example to illustrate the control and communication Linux thread. Contact a group of a group of consumers and the producer thread by thread occurred buffer. The producer thread production of goods into the buffer, the consumer thread is removed from the product. There are N buffers, an annular pool. 

[cpp] view plain copy

 

  1. #include <stdio.h>  
  2. #include <pthread.h>  
  3. 16 // number of buffers #define BUFFER_SIZE  
  4. struct prodcons  
  5. {  
  6.     // buffer data structure  
  7.     int buffer [BUFFER_SIZE]; / * store the actual data array * /  
  8.     pthread_mutex_t lock; / * mutex lock for mutual exclusion to the buffer * /  
  9.     int readpos, writepos; / * read pointer * /  
  10.     pthread_cond_t notempty; / * buffer is not empty condition variable * /  
  11.     pthread_cond_t notfull; / * buffer is not full in the condition variable * /  
  12. };  
  13. / * Initialize the buffer structure * /  
  14. void init(struct prodcons *b)  
  15. {  
  16.     pthread_mutex_init(&b->lock, NULL);  
  17.     pthread_cond_init(&b->notempty, NULL);  
  18.     pthread_cond_init(&b->notfull, NULL);  
  19.     b->readpos = 0;  
  20.     b->writepos = 0;  
  21. }  
  22. / * Product into the buffer zone, there is deposited an integer * /  
  23. void put(struct prodcons *b, int data)  
  24. {  
  25.     pthread_mutex_lock(&b->lock);  
  26.     / * Wait for the buffer is not full * /  
  27.     if ((b->writepos + 1) % BUFFER_SIZE == b->readpos)  
  28.     {  
  29.         pthread_cond_wait(&b->notfull, &b->lock);  
  30.     }  
  31.     / * Write data, and move the pointer * /  
  32.     b->buffer[b->writepos] = data;  
  33.     b->writepos++;  
  34.     if (b->writepos >= BUFFER_SIZE)  
  35.         b->writepos = 0;  
  36.     / * Set the buffer is not empty condition variable * /  
  37.     pthread_cond_signal(&b->notempty);  
  38.     pthread_mutex_unlock(&b->lock);  
  39. }   
  40. / * Integer removed from the buffer * /  
  41. int get(struct prodcons *b)  
  42. {  
  43.     int data;  
  44.     pthread_mutex_lock(&b->lock);  
  45.     / * Wait for the buffer is not empty * /  
  46.     if (b->writepos == b->readpos)  
  47.     {  
  48.         pthread_cond_wait(&b->notempty, &b->lock);  
  49.     }  
  50.     / * Read data, the read pointer moves * /  
  51.     data = b->buffer[b->readpos];  
  52.     b->readpos++;  
  53.     if (b->readpos >= BUFFER_SIZE)  
  54.         b->readpos = 0;  
  55.     / * Set the condition variable buffer is not full of * /  
  56.     pthread_cond_signal(&b->notfull);  
  57.     pthread_mutex_unlock(&b->lock);  
  58.     return data;  
  59. }  
  60.   
  61. / * Test: producer thread integer from 1 to 10,000 into the buffer, the consumer line 
  62.    Cheng obtain integer from the buffer, both print information * /  
  63. #define OVER ( - 1)  
  64. struct prodcons buffer;  
  65. void *producer(void *data)  
  66. {  
  67.     int n;  
  68.     for (n = 0; n < 10000; n++)  
  69.     {  
  70.         printf("%d --->\n", n);  
  71.         put(&buffer, n);  
  72.     } put(&buffer, OVER);  
  73.     return NULL;  
  74. }  
  75.   
  76. void *consumer(void *data)  
  77. {  
  78.     int d;  
  79.     while (1)  
  80.     {  
  81.         d = get(&buffer);  
  82.         if (d == OVER)  
  83.             break;  
  84.         printf("--->%d \n", d);  
  85.     }  
  86.     return NULL;  
  87. }  
  88.   
  89. int main(void)  
  90. {  
  91.     pthread_t th_a, th_b;  
  92.     void *retval;  
  93.     init(&buffer);  
  94.     / * Create the producer and consumer threads * /  
  95.     pthread_create(&th_a, NULL, producer, 0);  
  96.     pthread_create(&th_b, NULL, consumer, 0);  
  97.     / * Wait for the end of the two threads * /  
  98.     pthread_join(th_a, &retval);  
  99.     pthread_join(th_b, &retval);  
  100.     return 0;  
  101. }  


5.WIN32, VxWorks, Linux thread analogy 

so far, the author has created a "multi-task concurrent programming based on VxWorks embedded operating system design" ( "Software News" in 2006 from 5 to 12 serial), "in layman's language Win32 multi-threaded programs design "(NEW YORK technical topics) series, we have to find a common point of these two series of articles to this article. 

Look at technical issues to aim its nature, whether it is Linux, VxWorks or WIN32, it relates to the content of those parts are multithreaded, nothing more than a thread and thread control communications, many of their functions but different names, its real meaning is equivalent , here we come three columns a common operating system in detail form: 
 

matter WIN32 VxWorks Linux
Thread Creation CreateThread taskSpawn pthread_create
Thread Termination After the completion of the implementation of exit; thread function terminates their call ExitThread himself; by another thread function calls the function TerminateThread After the completion of the implementation of exit; exit to exit the call by the thread itself; termination of another thread calls the function taskDelete After the completion of the implementation of exit; pthread_exit call itself by a thread exit; termination of another thread calls the function pthread_cance
Get Thread ID GetCurrentThreadId taskIdSelf pthread_self
Creating mutually exclusive CreateMutex semMCreate pthread_mutex_init
Acquire the mutex WaitForSingleObject、WaitForMultipleObjects semTake pthread_mutex_lock
Release the mutex ReleaseMutex semGive phtread_mutex_unlock
Create Semaphore CreateSemaphore semBCreate、semCCreate sem_init
Waiting for the semaphore WaitForSingleObject semTake sem_wait
Release Semaphore ReleaseSemaphore semGive sem_post


6. Summary 

This chapter describes the Linux multithreading control and inter-thread communication program, shows an example of a producer / consumer, and Linux multithreading and WIN32, VxWorks multi-thread analogy, a general summary law. Given the multi-threaded programming has become the mainstream method development of concurrent applications, meaning they will learn in this chapter is self-evident.

Finish

[cpp] view plain copy

 

  1. #include <stdio.h>                                                                
  2. #include <stdio.h>  
  3. #include <pthread.h>  
  4. void thread(void)                                                                 
  5. {                                                                                 
  6.     int i;                                                                        
  7.     for(i=0;i<3;i++)                                                              
  8.         printf("This is a pthread.\n");                                           
  9. }  
  10.    
  11. int main(void)                                                                    
  12. {                                                                                 
  13.     pthread_t id;                                                                 
  14.     int i,ret;                                                                    
  15.     ret=pthread_create(&id,NULL,(void *) thread,NULL);                            
  16.     if(ret!=0){                                                                   
  17.         printf ("Create pthread error!\n");                                       
  18.         exit (1);                                                                 
  19.     }                                                                             
  20.     for(i=0;i<3;i++)                                                              
  21.         printf("This is the main process.\n");                                    
  22.     pthread_join(id,NULL);                                                        
  23.     return (0);                                                                   
  24. }  

 

编译:

gcc example1.c -lpthread -o example1

[cpp] view plain copy

 

  1. #include <pthread.h>  
  2. #include <stdio.h>  
  3. #include <sys/time.h>  
  4. #include <string.h>  
  5. #define MAX 10  
  6.    
  7. pthread_t thread[2];  
  8. pthread_mutex_t mut;  
  9. int number=0, i;  
  10.    
  11. void *thread1()  
  12. {  
  13.     printf ("thread1 : I'm thread 1\n");  
  14.     for (i = 0; i < MAX; i++)  
  15.         {  
  16.             printf("thread1 : number = %d\n",number);  
  17.             pthread_mutex_lock(&mut);  
  18.             number++;  
  19.             pthread_mutex_unlock(&mut);  
  20.             sleep(2);  
  21.         }  
  22.     printf("thread1 :主函数在等我完成任务吗?\n");  
  23.    
  24.     pthread_exit(NULL);  
  25.    
  26. }  
  27.    
  28. void *thread2()  
  29. {  
  30.     printf("thread2 : I'm thread 2\n");  
  31.     for (i = 0; i < MAX; i++)  
  32.         {  
  33.             printf("thread2 : number = %d\n",number);  
  34.             pthread_mutex_lock(&mut);  
  35.             number++;  
  36.             pthread_mutex_unlock(&mut);  
  37.             sleep(3);  
  38.         }  
  39.     printf("thread2 :主函数在等我完成任务吗?\n");  
  40.     pthread_exit(NULL);  
  41. }  
  42.    
  43.    
  44. void thread_create(void)  
  45. {  
  46.     int temp;  
  47.     memset(&thread, 0, sizeof(thread)); //comment1  
  48.     //创建线程  
  49.     if((temp = pthread_create(&thread[0], NULL, thread1, NULL)) != 0) //comment2  
  50.         printf("线程1创建失败!\n");  
  51.     else  
  52.         printf("线程1被创建\n");  
  53.     if((temp = pthread_create(&thread[1], NULL, thread2, NULL)) != 0) //comment3  
  54.         printf("线程2创建失败");  
  55.     else  
  56.         printf("线程2被创建\n");  
  57. }  
  58.    
  59. void thread_wait(void)  
  60. {  
  61.     //等待线程结束  
  62.     if(thread[0] !=0) { //comment4  
  63.         pthread_join(thread[0],NULL);  
  64.         printf("线程1已经结束\n");  
  65.     }  
  66.     if(thread[1] !=0) { //comment5  
  67.         pthread_join(thread[1],NULL);  
  68.         printf("线程2已经结束\n");  
  69.     }  
  70. }  
  71.    
  72. int main()  
  73. {  
  74.     //用默认属性初始化互斥锁  
  75.     pthread_mutex_init(&mut,NULL);  
  76.     printf("我是主函数哦,我正在创建线程,呵呵\n");  
  77.     thread_create();  
  78.     printf("我是主函数哦,我正在等待线程完成任务阿,呵呵\n");  
  79.     thread_wait();  
  80.     return 0;  
  81. }  

地址:https://www.cnblogs.com/cyyljw/p/7015774.html

发布了25 篇原创文章 · 获赞 4 · 访问量 2万+

Guess you like

Origin blog.csdn.net/zhou8400/article/details/83105082