Linux C multithreading __linux

Source: Internet
Author: User
Tags mutex posix prepare semaphore

One. Thread synchronization

1.posix Signal Volume:

With System V IPC Semaphore (Semget ...) Very similar, but not guaranteed to be interchangeable.

#include <semaphore.h>

Initialization function: Sem_init (sem_t * __sem,int __pshared,unsigned int __value);

_pshared Specifies the semaphore type, if 0, indicating that the semaphore is a local semaphore of the current process, otherwise the semaphore is shared by multiple processes. Initializing an already initialized semaphore result is not expected
Trigger Semaphore Value: Sem_post (sem_t * __sem), signal value plus 1.
have been waiting: sem_wait (sem_t * __sem); The value of the semaphore is reduced by one in atomic operation. If the semaphore value is 0, then the value of blocking to the semaphore is not 0

Sem_trywait (sem_t * __sem); Similar to sem_wait, it always returns immediately, and if the semaphore is not 0, then the minus action is performed. With a semaphore of 0, it will return-1 and set errno to Egain

Wait timeout: sem_timedwait (sem_t * __restrict __sem, __ const struct TIMESPEC * __restrict __abstime);
Release of the destruction signal: SEM _destroy (sem_t * __sem); Destroy a semaphore that is being waited, the result is not expected

The above functions successfully return 0, failure returns-1


2. Mutual exclusion Lock

#include <pthread.h>

A. Mutual-exclusion lock creation and destruction
There are two ways to create mutexes, both statically and dynamically. POSIX defines a macro pthread_mutex_initializer to statically initialize the mutex-actually initializes each of the mutex fields to 0, as follows:
pthread_mutex_t Mutex=pthread_mutex_initializer;
The dynamic approach is to initialize the mutex using the Pthread_mutex_init () function, which is defined as follows:
int Pthread_mutex_init (pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr)
Where mutexattr is used to specify the mutex attribute and, if NULL, to use the lack of a property.
Pthread_mutex_destroy () is used to unregister a mutex, and the API is defined as follows:
int Pthread_mutex_destroy (pthread_mutex_t *mutex)

B. Lock

int Pthread_mutex_lock (pthread_mutex_t *mutex)
int Pthread_mutex_unlock (pthread_mutex_t *mutex)
int Pthread_mutex_trylock (pthread_mutex_t *mutex)
The Pthread_mutex_trylock () semantics are similar to Pthread_mutex_lock (), but instead of suspending the wait when the lock is occupied, the Ebusy is returned. Note: Pthread_mutex_trylock () and Pthread_mutex_lock () are the differences between blocking and non-blocking for normal locks, but for other types of locks they can be different

 c. Sets/Gets the scope properties of the mutex-pshared
function pthread_mutexattr_setpshared The scope used to set the mutex. A
Mutex variable can be a process-specific variable or a variable that spans a process boundary.
The value of the Range property and its meaning:
pthread_process_shared: A mutex with this property can be shared among threads in multiple processes.
Pthread_process_private: The mutex variable can be used only in the line Cheng in the process where the thread creating this mutex is located. The value is the default value. The
function pthread_mutexattr_getpshared can be used to return the range of mutex variables set by pthread_mutexattr_setpshared.


D. set/Get Type properties for mutexes--type
Pthread_mutexattr_settype is used to set the type properties of the specified mutex. The default value for the Type property is Pthread_mutex_default.
Types of mutexes and their behavior:
Pthread_mutex_normal: Normal lock, default type. Deadlock detection is not provided. Attempting to lock the mutex will result in a deadlock. If a thread attempts to unlock a mutex that is not locked or unlocked by that thread, an indeterminate behavior is generated.
Pthread_mutex_errorcheck: provides error checking. An error EDEADLK is returned if a thread attempts to lock a lock that has been locked. If a thread attempts to unlock a mutex that is not locked or unlocked by that thread, an error eperm is returned.
Pthread_mutex_recursive: Nested lock, which retains the notion of a lock count. The lock count is set to 1 when the thread first succeeds in acquiring a mutex. The lock count increases by 1 each time the thread locks the mutex once. Each time the thread unlocks the mutex, the lock count is reduced by 1. When the lock count reaches 0, the mutex is available for other threads to acquire. If a thread attempts to unlock a mutex that is not locked or unlocked by that thread, an error eperm is returned.
Pthread_mutex_default: Attempting to lock the mutex recursively will result in an indeterminate behavior. For a mutex that is not locked by the calling thread, an indeterminate behavior can occur if an attempt is made to unlock it. If you attempt to unlock a mutex that has not been locked, an indeterminate behavior occurs. This lock may be mapped to one of the top three locks when implemented.


3. Condition variable: Transfer from http://blog.csdn.net/goodluckwhh/article/details/8564319

If a mutex is used to synchronize the access of a thread to shared data, the condition variable is used to synchronize the values of the shared data between threads.

When a shared data reaches a value, the thread that is waiting for the shared data is awakened.

#include <pthread.h>
int Pthread_cond_init (pthread_cond_t *cv, const pthread_condattr_t *cattr); success returns 0, other return values indicate an error

or pthread_cond_t Mycond = Pthread_cond_initializer
int pthread_cond_wait (pthread_cond_t *cv,pthread_mutex_t *mutex); success returns 0, other return values indicate an error
int pthread_cond_signal (pthread_cond_t *CV); success returns 0, other return values indicate an error
int pthread_cond_timedwait (pthread_cond_t *cv, pthread_mutex_t *mp, const struct TIMESPEC); success returns 0, other return values indicate an error
int pthread_cond_reltimedwait_np (pthread_cond_t *cv, pthread_mutex_t *mp, const struct TIMESPEC); successfully returned 0, Other return values indicate an error
int Pthread_cond_broadcast (pthread_cond_t *CV); success returns 0, other return values indicate an error
int Pthread_cond_destroy (pthread_cond_t *CV); success returns 0, other return values indicate an error

1 Initialization of the condition variableIf the condition variable variable is static, you can initialize it directly with Pthread_cond_initializer, for example:
static pthread_cond_t My_cond = Pthread_cond_initializer
If a condition variable is dynamically allocated, you must initialize it with Pthread_cond_init before using it.
Pthread_cond_init is used to initialize the condition variable that the CV points to, and if cattr is null, the condition variable is initialized with the default property, otherwise the condition variable is initialized with the property specified by Cattr.
Using the Pthread_cond_initializer macro is equivalent to dynamically assigning a pthread_cond_init () with a null property, except that the Pthread_cond_initializer macro does not perform error checking.
Multiple threads must not initialize or reinitialize the same condition variable at the same time. If you want to reinitialize or destroy a condition variable, the application must ensure that the condition variable is not in use.
2) blocking based on conditional variablesPthread_cond_wait releases the mutex that the mutex points to by atomic means and causes the calling thread to block on the condition variable that the CV points to.
Blocked threads can be awakened in the following ways:
Awakened by the pthread_cond_signal by the Pthread_cond_broadcast wake Pthread_cond_wait when returned, the mutex specified by the mutex is locked and held by the call lock, even if an error is returned.
Pthread_cond_wait will remain in a consistent state of blocking until awakened. It releases the associated mutex in atomic form before it is blocked, and acquires the mutex again in atomic form before returning.
Typically, the inspection of a conditional expression is performed under the protection of a mutex. If the conditional expression is false, the thread is blocked based on the condition variable. Then, when another thread changes the condition value, it wakes up (through pthread_cond_signal or pthread_cond_broadcast). This change can cause at least one thread that is waiting for the condition to unblock and try to acquire the mutex again.
You must test the condition that caused the wait before you can proceed from the pthread_cond_wait. Conditions may change before the awakened thread retrieves the mutex and returns from Pthread_cond_wait. The condition that waits for a thread lock may not actually occur. You typically use conditional variables in the following ways:
Pthread_mutex_lock ();
while (Condition_is_false)
Pthread_cond_wait ();
Pthread_mutex_unlock (); Pthread_cond_wait is a cancellation point. If there is a pending cancellation request and the thread has enabled the cancellation feature, the thread is terminated and the cleanup function is started in the state in which the lock continues to be held. If the lock is not released in the cleanup handler, the thread terminates but the lock is not released.
3) Unblocking threadPthread_cond_signal unblock the blocking state of one thread on the condition variable.
The relevant condition should be modified under the protection of the mutex, which is the mutex that is associated with the condition variable (that is, the mutex specified when calling Wati). Otherwise, the variable may be modified between the test of the condition variable and the pthread_cond_wait blocking, which can result in an indefinite wait.
If more than one thread is waiting for a condition variable, the order in which the thread is awakened is determined by the scheduling policy that is used.
If you are using the default scheduling policy, that is, sched_other, you cannot guarantee the wake order if you are using Sched_fifo or SCHED_RR, the thread is awakened according to priority if no thread is blocking based on a conditional variable, then the call to Pthread_cond_ Signal does not work.
4) Blocking before the specified timeThe usage of pthread_cond_timedwait is essentially the same as that of pthread_cond_wait, except that it is no longer blocked after the time specified by Abstime.
PTHREAD_COND_RELTIMEDWAIT_NP and pthread_cond_timedwait are basically the same, their only difference is pthread_cond_reltimedwait_ NP uses the relative time interval instead of the future absolute time as the value of its last parameter.
Similar to PTHREAD_COND_WAIT,PTHREAD_COND_RELTIMEDWAIT_NP and Pthread_cond_timedwait are also cancellation points.
5 Unblocking all threadsPthread_cond_broadcast the blocking of all threads that are blocked based on the condition variable.
The relevant condition should be modified under the protection of the mutex, which is the mutex that is associated with the condition variable (that is, the mutex specified when calling Wati). Otherwise, the variable may be modified between the test of the condition variable and the pthread_cond_wait blocking, which can result in an indefinite wait.
Because pthread_cond_broadcast causes all threads that are blocked based on this condition to compete again for mutexes, even with pthread_cond_broadcast, only one thread can actually get the lock and start running. Although there is only one thread that can run, this situation differs from the pthread_cond_signal:
If more than one thread is blocked on a condition variable, and pthread_cond_signal wakes one of the threads, the other threads are still waiting to be awakened and then trying to acquire the corresponding mutex, which blocks on the condition variable if multiple threads are blocking the condition variable, and the Pthread_ Cond_broadcast wakes them up, then all the threads start competing for the mutex, the winner starts executing, the loser blocks on the mutex if no thread is blocking based on the conditional variable, then the call Pthread_cond_broadcast does not work.
6) Destroy condition variable StatePthread_cond_destroy is used to destroy any state associated with the condition variable that the CV points to, but does not release the space used to store the condition variable.
7 Initialize the Property object of the condition variableConditional changes have properties that allow you to control some of the behavior of the condition variable by modifying these properties.
Pthread_condattr_init is used to initialize the property associated with the object to its default value. The Pthread_condattr_init argument type is actually opaque, which contains an attribute object that is assigned by the system. When the function is executed, the required memory is allocated for the Property object, thus causing a memory leak if the condition variable Property object is not destroyed by Pthread_condattr_destroy. For a Condition Variable Property object, you must first destroy it by calling Pthread_condattr_destroy to reinitialize the object.
8) Delete the Condition Variable Property objectPthread_condattr_destroy is used to destroy the specified condition variable Property object, which actually completes the process of releasing the memory allocated by Pthread_condattr_init.
9 Set/Get the Range property of the condition variablePthread_condattr_setpshared is used to set the scope of a condition variable to a process-specific (in-process) or system-wide (inter-process).
The value of the Range property and its meaning:
Pthread_process_shared: A condition variable with this property can be shared among threads in multiple processes. Pthread_process_private: This condition variable can be used only in a line within the process where the thread that created this condition variable Cheng. The value is the default value. Pthread_condattr_getpshared is used to get the current value of the Range property cattr the Condition Variable Property object.

Two. Threads and processes

Threads share process data (4G memory address space, global variable, file descriptor, signal processing, working directory), but there are unique data for each thread: Thread ID, a set of registers, stacks, errno, signal State (signal mask), priority

1. After a child thread in a multithreaded program invokes fork, the subprocess has only one thread of execution, the full copy of the child thread that called the fork function, and the child process automatically inherits the state of the mutex and condition variable in the process. This raises the question that the child process is not aware of the specific state of the mutex inherited from the parent process-lock or unlocking, and that the mutex may be locked, not by the thread that invoked the fork function, but by another thread. In this case, a child process that locks the mutex again causes the deadlock. (Mutual-exclusion locks, conditional variables are shared by the threads in the same process), Workaround:

called before the fork call Pthread_atfork

function pthread_atfork (void (*prepare) (void), void (*parent) (void), void (*child) (void);

prepare is executed before the fork call creates a subprocess, and is used to lock mutexes in all parent processes. Parent is a fork call to create a subprocess, and fork is executed in the parent process before returning. Its role is to release all mutexes locked in the prepare. The child is fork before it is returned and executed in the subprocess.  As with parent, frees all mutex locks that are locked in prepare. Successfully returned 0, failure returned error code

prepare, parent, child to realize

The 2.exit function call causes the entire process to exit, the thread exits with Viod pthread_exit (void *arg), and Arg can be caught by another thread calling Pthread_join (pthread_t pt,void **rearg). The thread resources of the PT are recycled at the same time, each thread is pthread_join to recycle. If the other thread calls Pthread_detach (pthread_t PT) to detach the PT thread, the system automatically reclaims resources after the PT thread exits. (When using Pthread_join to wait for a thread to reclaim the detach state, return the error einval)

The main thread exits and the whole process ends.

In addition to calling Pthread_detach (pthread_t PT) Detach, thread separation can also be set by setting the property when the thread is created:

pthread_attr_t attr;
Pthread_attr_init (&ATTR);
Pthread_attr_setdetachstate (&attr, pthread_create_detached);/set thread to separable state

Pthread_create (&thr_d, &attr, func, param);

Three. Threads and Signals

all threads in the process share the signal of the process, and all threads share the signal processing function------One thread to set the signal processing function to overwrite the handler function that other threads set for the same signal .... All it is best to set up signal processing before creating a new thread.

Sigprocmask is to set the process signal mask, Pthread_sigmask can independently set the signal mask for each thread

We should define a dedicated thread to handle all the signals that are implemented:

1. Call Phtread_sigmask to set the signal mask before the main thread creates other child threads, and all created child threads will automatically inherit this signal mask

2. Call the following function in a thread to wait for the signal and process it

#include <signal.h>

int sigwait (const sigset_t* set,int* sig);

SET specifies the set of signals to wait, we can simply specify the signal mask created in the first step, indicating that the thread waits for all masked signals that the SIG uses to store the signal value returned by the function. Once the sigwait is properly returned, we can process the received SIG signal. Obviously, when we use sigwait, we should not set the signal processing function for the signal, because when the program receives the signal, there is only one effect.

int Phread_kill (pthread_t thread,int SIG): Sends a signal to a specified thread

PS: When a thread A gives another thread B data, it is best to use the data generated by malloc heap memory, only thread B remember to release the memory

Related Article

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.