Multi-threaded programming of the apue3rd_chapter11 of the mutual exclusion lock _ read-write lock _ Spin lock

Source: Internet
Author: User
Tags mutex posix semaphore

Learn the 11th chapter of apue3rd, the main talk is multithreaded programming. Because multithreading shares the resources of a process such as heaps and global variables, multithreaded programming is most important for thread synchronization using various locks.

The first three functions to be learned in threading are as follows:

#include <pthread.h>

int Pthread_create (pthread_t* TIDP, const pthread_attr_t* restrict attr, void* (*start rm) (void*), void* restrict Arg)

This function is responsible for thread creation. The first parameter is the thread ID, and after the thread is created successfully, the thread ID is written to the memory that TIDP points to. Under Linux, pthread_t is the unsigned long type. The second parameter is a struct pointer, which is a property passed to the thread, determines a lot of behavior of the thread, and if not used, it can pass a null to attr. The third is the thread's starting function, which must be void* xxxxx (void* arg) type, that is, the return value and parameter are void* pointers. The fourth is the argument passed to the start function, and after startup, the value of the parameter arg of the start function equals the value of Pthread_create Arg.

void Pthread_exit (void * rval_ptr)

This function can terminate the exit of a thread. Rval_ptr is a pointer you set, which points to the memory that can hold the terminating state information structure you want to return.

int Pthread_join (pthread_t thread, void** rval_ptr)

This function is used to recycle the resources of other threads on the bus path. Rval_ptr points to the address that will be written on the value of the pointer returned from Pthread_exit, thereby obtaining the struct body to terminate the state.

Example code: GCC main.c-o main-lpthread

#include <pthread.h>

#include <stdio.h>

#include <stdlib.h>

void* thread1 (void* Arg)

{

Pthread_exit ((void*) 2);

}

int main (int argc, char* argv[])

{

pthread_t Tid1;

int res;

void* Rval;

res = pthread_create (&tid1,null,thread1,null);

if (res!=0)

{

printf ("Thread creating failed!\n");

Exit (Exit_failure);

}

res = Pthread_join (tid1,&rval);

if (res!=0)

{

printf ("Thread join failed\n");

Exit (Exit_failure);

}

printf ("Thread exit code is%lu\n", (unsigned long) rval);//Online said unsigned long reorganization output format is//lu

return 0;

}

The compilation appears stray ' \241 ' in the program, the reason is the double quotation marks in Word, copied into the text file, and should have the English double quotation marks, should re-use the English input method double quotation marks. Exit_failure's header file is Stdlib.h

Mutual exclusion Lock

A mutex is a thread synchronization method similar to the POSIX semaphore, which essentially acquires a lock by atomic manipulation. Its functions are as follows.

int Pthread_mutex_init (pthread_mutex_t* restrict mutex,const pthread_mutexattr_t* restrict attr)

This function initializes the lock before the mutex is used. The parameters are pointers to the mutex structure body and the mutex property structure, respectively.

int Pthread_mutex_destroy (pthread_mutex_t* mutex)

After this function is used, the mutex is destroyed.

int Pthread_mutex_lock (pthread_mutex_t* mutex)

int Pthread_mutex_unlock (pthread_mutex_t* mutex)

The two functions are acquiring locks and releasing locks, respectively.

It should be noted that if a thread has acquired a lock and continues to acquire the lock, it will generate a deadlock.

If a thread has already released a lock, releasing that lock again does not result in a deadlock, but an error occurs when the lock is destroyed.

The mutex exists only in the process and does not exist in the kernel, so the kernel will not have a lock left before the lock of a process ends without destroying it.

int Pthread_mutex_timedlock (pthread_mutex_t* restrict mutex,const struct timespec* restrict tsptr)

When the function acquires the lock, it avoids the deadlock, and if the lock is not taken to a time period, the function returns and the return code is eimedout. Note that the tsptr here is the absolute time, that is, the number of seconds and nanoseconds starting from Utc1970-1-1 0:0:0. Use Clock_gettime to get the absolute time of the system. And then add a time interval,

GCC Main.c-o MAIN-LPTHREAD-LRT-LRT exists because of the use of clock_gettime, which requires a link library Rt. Note that the "-" symbol here is sometimes wrong when pasting to Linux, you need to use the English input method to re-hit "-".

When used, the lock is generally defined as a global variable, which makes it easy for each thread to use. The test code is as follows (modified on the basis of the above code):

#include <pthread.h>

#include <stdio.h>

#include <stdlib.h>

#include <time.h>

pthread_mutex_t mutex1;

void* thread1 (void* Arg)

{

int res;

struct Timespec tout; Defined in Time.h

memset (&tout, 0, sizeof (tout));

Clock_gettime (Clock_realtime, &tout);

Tout.tv_sec + = 10;

Pthread_mutex_lock (&MUTEX1);

res = Pthread_mutex_timedlock (&mutex1,&tout);

printf ("Timedlock return%d\n", res);

printf ("%s\n", Strerror (res)); Strerror in Errno.h

Pthread_mutex_lock (&MUTEX1);

Pthread_mutex_unlock (&MUTEX1);

Pthread_mutex_unlock (&MUTEX1);

Pthread_exit ((void*) 2);

}

int main (int argc, char* argv[])

{

pthread_t Tid1;

int res;

void* Rval;

res = Pthread_mutex_init (&mutex1,null); NULL is defined in stdio.h

if (res!=0)

{

printf ("Mutex init failed!\n");

Exit (Exit_failure);

}

res = pthread_create (&tid1,null,thread1,null);

if (res!=0)

{

printf ("Thread creating failed!\n");

Exit (Exit_failure);

}

res = Pthread_join (tid1,&rval);

if (res!=0)

{

printf ("Thread join failed\n");

Exit (Exit_failure);

}

printf ("Thread exit code is%lu\n", (unsigned long) rval);//Online said unsigned long reorganization output format is//lu

res = Pthread_mutex_destroy (&MUTEX1);

if (res!=0)

{

printf ("Mutex destroy failed!\n");

Exit (Exit_failure);

}

return 0;

}

Read/write Lock

The use of a read-write lock is very similar to a mutex, and it is suitable for scenarios where there is a lot of reading, and only a small amount of writing can allow more threads to execute forward.

int Pthread_rwlock_init (pthread_rwlock_t* restrict rwlock,const pthread_rwlockattr_t* restrict attr)

int Pthread_rwlock_destroy (pthread_rwlock_t* rwlock)

int Pthread_rwlock_rdlock (pthread_rwlock_t* rwlock)

int Pthread_rwlock_wrlock (pthread_rwlock_t* rwlock)

int Pthread_rwlock_unlock (pthread_rwlock_t* rwlock)

Spin lock

Spin lock is similar to a mutex, it is suitable for the scene is the thread each execution time is very short, other threads do not need to wait for how long the situation, spin lock waiting, the thread does not hibernate, but in a constant cycle of death. A spin lock is a case where the overhead of a spin wait is less than the overhead of a thread switch.

int Pthread_spin_init (pthread_spinlock_t* lock, int pshared)

int Pthread_spin_destroy (pthread_spinlock_t* lock)

int Pthread_spin_lock (pthread_spinlock_t* lock)

int Pthread_spin_unlock (pthread_spinlock_t* lock)

int Pthread_spin_trylock (pthread_spinlock_t* lock)

Whether it is a mutex, or a read-write lock, or a spin lock, or a previously learned POSIX semaphore, there is a problem, that is, when multiple threads are competing for a lock, there is a thread running too fast to get the lock repeatedly, and the other threads have no chance to compete for the lock (the Resurrection thread takes time). After releasing the lock, The empty loop takes a certain amount of time (5000-10000 times) to allow the other threads sufficient time to obtain the lock. This is the question which the interviewer of Nanjing Huawei asked me.

GCC Main.c-o MAIN-LPTHREAD–LRT

#include <pthread.h>

#include <stdio.h>

#include <stdlib.h>

#include <time.h>

pthread_mutex_t mutex1;

pthread_spinlock_t spin1;

pthread_rwlock_t Rwlock1;

void* thread1 (void* Arg)

{

int res;

struct Timespec tout; Defined in Time.h

memset (&tout, 0, sizeof (tout));

Clock_gettime (Clock_realtime, &tout);

Tout.tv_sec + = 5;

Pthread_mutex_lock (&MUTEX1);

res = Pthread_mutex_timedlock (&mutex1,&tout);

printf ("Timedlock return%d\n", res);

printf ("%s\n", Strerror (res)); Strerror in Errno.h

Pthread_mutex_lock (&MUTEX1);

Pthread_mutex_unlock (&MUTEX1);

Pthread_mutex_unlock (&MUTEX1);

Pthread_spin_lock (&spin1);

Pthread_spin_unlock (&spin1);

Pthread_rwlock_rdlock (&RWLOCK1);

Pthread_rwlock_unlock (&RWLOCK1);

Pthread_rwlock_wrlock (&RWLOCK1);

Pthread_rwlock_unlock (&RWLOCK1);

Pthread_exit ((void*) 2);

}

int main (int argc, char* argv[])

{

pthread_t Tid1;

int res;

void* Rval;

res = Pthread_mutex_init (&mutex1,null); NULL is defined in stdio.h

if (res!=0)

{

printf ("Mutex init failed!\n");

Exit (Exit_failure);

}

res = Pthread_spin_init (&spin1,pthread_process_private);

if (res!=0)

{

printf ("Spin init failed!\n");

Exit (Exit_failure);

}

res = Pthread_rwlock_init (&rwlock1,null);

if (res!=0)

{

printf ("Rwlcok init failed!\n");

Exit (Exit_failure);

}

res = pthread_create (&tid1,null,thread1,null);

if (res!=0)

{

printf ("Thread creating failed!\n");

Exit (Exit_failure);

}

res = Pthread_join (tid1,&rval);

if (res!=0)

{

printf ("Thread join failed\n");

Exit (Exit_failure);

}

printf ("Thread exit code is%lu\n", (unsigned long) rval);//Online said unsigned long reorganization output format is//lu

res = Pthread_mutex_destroy (&MUTEX1);

if (res!=0)

{

printf ("Mutex destroy failed!\n");

Exit (Exit_failure);

}

res = Pthread_spin_destroy (&spin1);

if (res!=0)

{

printf ("Spin destroy failed!\n");

Exit (Exit_failure);

}

res = Pthread_rwlock_destroy (&RWLOCK1);

if (res!=0)

{

printf ("Rwlock destroy failed!\n");

Exit (Exit_failure);

}

return 0;

}

Multi-threaded programming of the apue3rd_chapter11 of the mutual exclusion lock _ read-write lock _ Spin lock

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.