Linux multithreading mechanisms (producer and consumer instances)

Source: Internet
Author: User

One of the reasons to use multithreading is that it is a very "frugal" multi-tasking approach compared to the process. We know that under the Linux system, starting a new process must be assigned to its own address space, creating numerous data tables to maintain its code snippets, stack segments, and data segments, which is an "expensive" multi-tasking way of working. While running on multiple threads in a process that use the same address space, sharing most of the data, starting a thread is much less than the space it takes to start a process, and the time it takes to switch between threads is much less than the time it takes to switch between processes.

The second reason to use multithreading is the convenient communication mechanism between threads. For different processes, they have independent data space, it is not only time-consuming, but also inconvenient to transmit the data only by means of communication. Threads do not, because data space is shared between threads in the same process, so that the data of one thread can be used directly by other threads, which is not only fast, but also convenient. Of course, the sharing of data also brings some other problems, some variables can not be modified by two threads at the same time, some of the sub-programs declared as static data more likely to have a catastrophic attack on the multi-threaded program, these are the most important to write a multi-thread programming.


1. Brief description of function syntax.

creation and termination of threadspthread_create

Header file: pthread.h

function prototypes: int pthread_create (pthread_t* thread, pthread_attr_t* attr,

void* (Start_routine) (void*), void* Arg);

function passed in value: Thread: Threading identifier

attr: Thread property setting

Start_routine: Thread function entry

ARG: Arguments passed to a thread function

Return value: 0: Success

-1: Failure

Call this function to create a new thread that executes start_routine the specified program after the new thread is created. Where the parameter attr is the property that the user wants to create the thread in, and when NULL indicates that the thread is created with the default property. ARG is a parameter passed to the Start_routine. When a new thread is created successfully, the system automatically assigns a thread ID number to the new thread and returns it to the caller via Pthread.

Pthread_exit

Header file: pthread.h

Function prototype: void pthread_exit (void *value_ptr);

The function passes in the value: Retval:pthread_exit () The return value of the caller's thread, but other functions such as Pthread_join retrieve the fetch.

call this function to exit the thread, parameter Value_ptr is a pointer to the return status value.

Phread_join

Header file: pthread.h

Function prototype: int pthread_join (pthread_t* thread, void** thread_return);

function passed in value: thread: The identifier of the waiting thread.

Thread_return: User-defined pointer to store the return value of the waiting thread (not a null value);

function return value: Success: 0

Failed:-1

This function is to wait for the end of a thread. The thread that calls Pthread_join () is suspended until the thread ID for the thread specified by the parameter thread terminates.

Pthread_self (void);

To differentiate threads, the system assigns a unique ID number to the thread when it is created , is returned by Pthread_create () to the caller, or it can get its own thread ID by pthread_self ().

Pthread_detachCreate a thread the default state is joinable, if a thread ends up running but not being join, its state is similar to the zombie process in progress, that is, some of the resources are not recycled (exit status code), so the creator thread should call Pthread_ Join to wait for the thread to run to the end and get the thread's exit code to reclaim its resources (similar to wait,waitpid)but after calling Pthread_join (pthread_id), if the thread is not running at the end, the caller will be blocked, in some cases we do not want this, such as in the Web server when the main thread for each new link to create a child thread for processing, The main thread does not want to be blocked by calling Pthread_join (because it has to continue processing the incoming link), you can add code to the child threadPthread_detach (Pthread_self ())or the parent thread callsPthread_detach (thread_id) (non-blocking, can be returned immediately)This sets the state of the child thread to detached, which automatically frees all resources when the thread finishes running.

Linux thread execution differs from windows in that Pthread has two state joinable states and unjoinable states.
If the thread is in the joinable state, both the stack and the thread descriptor (totaling 8K) are not freed when the thread function returns to exit or Pthread_exit. These resources will be released only if you call Pthread_join.
These resources are automatically freed when the thread function exits or pthread_exit, if the threads are in a unjoinable state.

The Unjoinable property can be specified at pthread_create time, or Pthread_detach itself in the thread after the thread is created, such as: Pthread_detach (Pthread_self ()), Change the status to Unjoinable state to ensure the release of the resource. or set the thread to joinable, and then call Pthread_join as appropriate.

Pthread_mutex_init

Header files: <pthread.h>

function prototypes: int pthread_mutex_init (pthread_mutex_t* mutex,

Const pthread_mutexattr_t* mutexattr);

function passed in value: Mutex: Mutex.

Mutexattr:pthread_mutex_initializer: Create a quick mutex.

PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP: Creates a recursive mutex.

PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP: Creates a fault-checking mutex.

function return value: Success: 0

Error:-1

Lock function:

int Pthread_mutex_lock (pthread_mutex_t* mutex);

int Pthread_mutex_trylock (pthread_mutex_t* mutex);

int Pthread_mutex_unlock (pthread_mutex_t* mutex);

int Pthread_mutex_destroy (pthread_mutex_t* mutex);

function passed in value: Mutex: Mutex.

function return value: Ibid.

pthread_mutex_init (pthread_mutex_t *mutex,const pthread_mutexattr_t *attr); At the beginning of a mutex variable mutex, The parameter attr means that the mutex is created by the Attr property, and if the parameter attr is null, it is created by default. Pthread_mutex_lock (pthread_mutex_t *mutex); Locks a mutex variable, if the mutex specified by the mutex has been locked, The calling thread is blocked until the thread that owns the mutex unlocks the mutex. Pthread_mutex_unlock (pthread_mutex_t *mutex), unlocks the mutex variable specified by the parameter mutex. Synchronization between Threadssynchronization is when a thread waits for an event to occur, and the waiting thread and event continue to execute when the awaited event occurs. Hangs if the awaited event does not arrive. synchronization is achieved through conditional variables in the Linux operating system. pthread_cond_init (pthread_cond_t *cond,const pthread_cond_t *attr); This function causes a conditional variable to be attr at the beginning of a parameter cond the specified property. pthread_cond_wait (pthread_cond_t *cond,pthread_mutex_t *mutex); Waits for an event (condition variable) to occur, the thread that makes the call automatically blocks until the corresponding condition variable is set to 1. Threads that wait for status do not consume CPU time. pthread_cond_signal (pthread_cond_t *cond); Unlocks the blocking state of a thread that waits for a parameter cond the specified condition variable.      producer and consumer issues, the producer thread writes data to a buffer, the consumer thread reads the data from the buffer, and because the producer and consumer threads share the same buffer, in order to read and write the data correctly, the buffer queue must remain mutually exclusive. Producer and consumer threads must meet: The number of producer write buffers cannot exceed the buffer capacity, and the number of consumers reading cannot exceed the number written by the producer. A small trick is used in the program to determine whether the buffer is empty or full. The read pointer and the write pointer are 0 at initialization time, if the read pointer equals the write pointer, the buffer is empty, if (write pointer + 1)% N equals the read pointer, the buffer is full, and% indicates the remainder, when there is actually a unit that is unused.

#include <stdio.h> #include <stdlib.h> #include <time.h> #include <pthread.h> #define Buffer_     SIZE 8 struct Prodcons {int buffer[buffer_size];      pthread_mutex_t lock;     Mutex lock int readpos, Writepos;   pthread_cond_t Notempty;    Buffer non-null condition to judge pthread_cond_t Notfull;    Buffer not full condition judgment};void init (struct prodcons * b) {pthread_mutex_init (&b->lock,null);    Pthread_cond_init (&b->notempty,null);    Pthread_cond_init (&b->notfull,null);    b->readpos=0; B->writepos=0;}    void put (struct prodcons* b,int data) {Pthread-_mutex_lock (&b->lock);  if ((B->writepos + 1)% Buffer_size = = B->readpos) {pthread_cond_wait (&b->notfull, &b->lock)    ;    } b->buffer[b->writepos]=data;        b->writepos++;       if (B->writepos >= buffer_size) b->writepos=0;    Pthread_cond_signal (&b->notempty); Pthread_mutex_unlock (&b->lock);} int get (struct prodcons *b) {int dAta    Pthread_mutex_lock (&b->lock);    if (B->writepos = = B->readpos) {Pthread_cond _wait (&b->notempty, &b->lock);    } data = b->buffer[b->readpos];    b->readpos++;       if (B->readpos >= buffer_size) b->readpos=0;    Pthread_cond_signal (&b->notfull);    Pthread_mutex_unlock (&b->lock); return data;}        #define OVER ( -1) struct prodcons buffer;void *producer (void *data) {int n;        for (n = 0; n < 10000; n++) {printf ("%d \ n", n.);    Put (&buffer, n);     } put (&buffer, over); return NULL;}        void *consumer (void * data) {int D;        while (1) {d = Get (&buffer);             if (d = = over) break;    printf ("%d\n", D); } return NULL;       int main (void) {pthread_t th_a, th_b;        void *retval;        Init (&buffer);    Pthread_create (&th_a, NULL, producer, 0);        Pthread_create (&th_b, NULL, consumer, 0); PthreAd_join (Th_a, &retval);    Pthread_join (Th_b, &retval); return 0;}

The producer is responsible for writing a 1 to 1000 integer to the buffer, and the consumer is responsible for reading the written integer from the same buffer and printing it. Because the producer and consumer are two concurrently running threads and want to use the same buffer for data exchange, a mechanism must be used for synchronization.The biggest benefit of multithreading is that almost all of the data is shared in addition to the stack, so communication between threads is highly efficient; Disadvantage: Because all data is shared, it is very easy to cause the data to break between threads.





Copyright NOTICE: This article for Bo Master original article, without Bo Master permission not reproduced.

Linux multithreading mechanisms (producer and consumer instances)

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.