Use pthread_mutex_init and other multi-threaded functions Detailed

In accordance with its thread scheduler can be divided into user-level threads and kernel-level thread two kinds 

User-level threads to solve the main problem is that context switching, its scheduling algorithms and scheduling of all selection decisions on their own by the user, it does not require specific kernel support at run time; 
we used is the basic user-level threads, so we only summarize POSIX the interface provides user-level threads; 
function associated with the basic thread operations: 
1 the end of the thread to establish 
two mutually exclusive and synchronization thread 
3 using the signal to control the amount of thread 
basic properties of four thread arranged 

substantially thread operations:

function Explanation
pthread_create() Create a thread starts running thread related functions, the end of the running thread exit
pthread_eixt() Because exit () is used to end the process, so you need to use a specific function of the end of the thread
pthread_join() Suspend the current thread, waiting for blocking the end of the thread, if the thread has ended immediately return 0 = success
pthread_cancel() Send a termination signal to the thread thread, it returns 0 on success, but success does not mean that thread will terminate
pthread_testcancel() Create a cancellation point in a place that does not contain a cancellation point, but they need to cancel points, so that does not contain a code execution thread cancellation point in response to a cancellation request.
pthread_setcancelstate() This thread is provided in response to signals Cancel
pthread_setcanceltype() Setting canceled state continues to run to the next point and then withdraw or cancel the implementation of the action immediately cancel
pthread_setcancel() Set status canceled


Mutual exclusion and synchronization mechanisms basic functions

function Explanation
pthread_mutex_init() Mutex initialization
pthread_mutex_lock() Mutex lock, if you try to lock the mutex has been locked to the blockage becomes available
pthread_mutex_trylock() Non-blocking lock mutex
pthread_mutex_unlock() Release mutex
pthread_mutex_destory() Mutex destructor


Semaphore thread control (default unnamed semaphore)

function Explanation
sem_init (not) Anonymous initialize a semaphore is positioned in the sem
sem_wait () The operation signal minus 1, if the current value of the semaphore into the obstruction 0, an atomic operation
sem_trywait () If the semaphore's current value is 0 errors returned instead of blocking call (errno = EAGAIN), in fact, is sem_wait () is a non-blocking version
sem_post () To the semaphore value plus 1, which is a "atomic operation", i.e., while doing the same amount was added to a 1 signal, the operation of the two threads is not conflict
sem_getvalue(sval) Sem points to the amount of the signal is placed on the current value of the integer directed sval
sem_destory (free) Anonymous destroyed by the semaphore pointed to sem


Thread related property configuration function

function Explanation
pthread_attr_init() The initial configuration of a thread object attributes, you need to remove an existing property with pthread_attr_destroy function
pthread_attr_setscope() Set thread attributes
pthread_attr_setschedparam() Set thread priority
pthread_attr_getschedparam() Get the Thread Priority

 

Establish basic thread running pthread_create

 
 
  1. /* thread.c */

  2. #include <stdio.h>

  3. #include <stdlib.h>

  4. #include <pthread.h>

  5.  
  6. #define THREAD_NUMBER 3 /*线程数*/

  7. #define REPEAT_NUMBER 5 /*每个线程中的小任务数*/

  8. #define DELAY_TIME_LEVELS 10.0 /*小任务之间的最大时间间隔*/

  9. //

  10. void *thrd_func(void *arg) {

  11. /* 线程函数例程 */

  12. int thrd_num = (int)arg;

  13. int delay_time = 0;

  14. int count = 0;

  15. printf("Thread %d is starting\n", thrd_num);

  16. for (count = 0; count < REPEAT_NUMBER; count++) {

  17. delay_time = (int)(rand() * DELAY_TIME_LEVELS/(RAND_MAX)) + 1;

  18. sleep(delay_time);

  19. printf("\tThread %d: job %d delay = %d\n",

  20. thrd_num, count, delay_time);

  21. }

  22.  
  23. printf("Thread %d finished\n", thrd_num);

  24. pthread_exit(NULL);

  25. }

  26.  
  27. int main(void) {

  28. pthread_t thread[THREAD_NUMBER];

  29. int no = 0, res;

  30. void * thrd_ret;

  31. srand(time(NULL));

  32. for (no = 0; no < THREAD_NUMBER; no++) {

  33. /* 创建多线程 */

  34. res = pthread_create(&thread[no], NULL, thrd_func, (void*)no);

  35. if (res != 0) {

  36. printf("Create thread %d failed\n", no);

  37. exit(res);

  38. }

  39. }

  40.  
  41. printf("Create treads success\n Waiting for threads to finish...\n");

  42. for (no = 0; no < THREAD_NUMBER; no++) {

  43. /* 等待线程结束 */

  44. res = pthread_join(thread[no], &thrd_ret);

  45. if (!res) {

  46. printf("Thread %d joined\n", no);

  47. } else {

  48. printf("Thread %d join failed\n", no);

  49. }

  50. }

  51. return 0;

  52. }


 

  • Routine 3 cycles to establish three threads, and use pthread_join function in order to wait for the end of the thread; 

Thread using rand () Gets a random value random sleep five times, after random thread of execution will be finished first; 
result:

 
 
  1. $ gcc thread.c -lpthread

  2. $ ./a.out

  3. Create treads success

  4. Waiting for threads to finish...

  5. Thread 0 is starting

  6. Thread 1 is starting

  7. Thread 2 is starting

  8. Thread 1: job 0 delay = 2

  9. Thread 1: job 1 delay = 2

  10. Thread 0: job 0 delay = 8

  11. Thread 2: job 0 delay = 10

  12. Thread 2: job 1 delay = 3

  13. Thread 1: job 2 delay = 10

  14. Thread 0: job 1 delay = 8

  15. Thread 0: job 2 delay = 3

  16. Thread 0: job 3 delay = 1

  17. Thread 2: job 2 delay = 8

  18. Thread 1: job 3 delay = 8

  19. Thread 1: job 4 delay = 1

  20. Thread 1 finished

  21. Thread 2: job 3 delay = 6

  22. Thread 0: job 4 delay = 7

  23. Thread 0 finished

  24. Thread 0 joined

  25. Thread 1 joined

  26. Thread 2: job 4 delay = 10

  27. Thread 2 finished

  28. Thread 2 joined


 

  • Can be seen, thread 1 performed prior to thread 0, but pthread_join calls in chronological order, wait thread 0 execution; 

Since the thread 1, it has already ended, so the thread 0 is pthread_join wait time, thread 1 has ended, just waiting to thread 1, direct return; 
 

Mutual exclusion and synchronization thread execution pthread_mutex_lock

Mutex increase in the above procedure

 
 
  1. /*thread_mutex.c*/

  2. #include <stdio.h>

  3. #include <stdlib.h>

  4. #include <pthread.h>

  5.  
  6. #define THREAD_NUMBER 3 /* 线程数 */

  7. #define REPEAT_NUMBER 3 /* 每个线程的小任务数 */

  8. #define DELAY_TIME_LEVELS 10.0 /*小任务之间的最大时间间隔*/

  9. pthread_mutex_t mutex;

  10.  
  11. void *thrd_func(void *arg) {

  12. int thrd_num = (int)arg;

  13. int delay_time = 0, count = 0;

  14. int res;

  15. /* 互斥锁上锁 */

  16. res = pthread_mutex_lock(&mutex);

  17. if (res) {

  18. printf("Thread %d lock failed\n", thrd_num);

  19. pthread_exit(NULL);

  20. }

  21. printf("Thread %d is starting\n", thrd_num);

  22. for (count = 0; count < REPEAT_NUMBER; count++) {

  23. delay_time = (int)(rand() * DELAY_TIME_LEVELS/(RAND_MAX)) + 1;

  24. sleep(delay_time);

  25. printf("\tThread %d: job %d delay = %d\n",

  26. thrd_num, count, delay_time);

  27. }

  28. printf("Thread %d finished\n", thrd_num);

  29. pthread_exit(NULL);

  30. }

  31.  
  32. int main(void) {

  33. pthread_t thread[THREAD_NUMBER];

  34. int no = 0, res;

  35. void * thrd_ret;

  36.  
  37. srand(time(NULL));

  38. /* 互斥锁初始化 */

  39. pthread_mutex_init(&mutex, NULL);

  40. for (no = 0; no < THREAD_NUMBER; no++) {

  41. res = pthread_create(&thread[no], NULL, thrd_func, (void*)no);

  42. if (res != 0) {

  43. printf("Create thread %d failed\n", no);

  44. exit(res);

  45. }

  46. }

  47. printf("Create treads success\n Waiting for threads to finish...\n");

  48. for (no = 0; no < THREAD_NUMBER; no++) {

  49. res = pthread_join(thread[no], &thrd_ret);

  50. if (!res) {

  51. printf("Thread %d joined\n", no);

  52. } else {

  53. printf("Thread %d join failed\n", no);

  54. }

  55. }

  56. /****互斥锁解锁***/

  57. pthread_mutex_unlock(&mutex);

  58. pthread_mutex_destroy(&mutex);

  59. return 0;

  60. }


 

  • Added directly above routine pthread_mutex_t synchronization lock; 

Join in the thread, so the program is executed thread program; 
calls pthread_mutex_lock locked, found locked when entering the waiting, waiting for re-locked after the lock is released again; 
so-threaded programs loaded into the waiting queue, waiting to continue successfully unlocked executing program code; 
operating results

 
 
  1. $gcc thread_mutex.c -lpthread

  2. $ ./a.out

  3. Create treads success

  4. Waiting for threads to finish...

  5. Thread 0 is starting

  6. Thread 0: job 0 delay = 9

  7. Thread 0: job 1 delay = 4

  8. Thread 0: job 2 delay = 7

  9. Thread 0 finished

  10. Thread 0 joined

  11. Thread 1 is starting

  12. Thread 1: job 0 delay = 6

  13. Thread 1: job 1 delay = 4

  14. Thread 1: job 2 delay = 7

  15. Thread 1 finished

  16. Thread 1 joined

  17. Thread 2 is starting

  18. Thread 2: job 0 delay = 3

  19. Thread 2: job 1 delay = 1

  20. Thread 2: job 2 delay = 6

  21. Thread 2 finished

  22. Thread 2 joined


 

  • 1 routines with different execution result, the thread program is loaded into the queue can not be executed immediately, it waits to successfully locked; 

After locking, the program continues to execute threads, lock execution; 
the case of such threads are executed in sequence often occur in actual use scenarios; 
usage scenarios: 
when the user logs on to obtain the secret key to continue getting the basic information of the user; to wait when we can proceed to obtain user information log on after the end of the thread thread 
needs to call two threads, if it is: threadLogin (), threadGetInfo () ; you can have two kinds of ways: 
1 At this point you can use a mutex while disposable End call threadLogin () and threadGetInfo (); 
2 may not be used of course call threadGetInfo (mutex directly after threadLogin () in the login authentication success); 
in contrast, a clearer display mode logic, add code readability scalability.

Controlling the order of execution threads using semaphores sem_post

Modify the above routine, using the above pthread_mutex_lock mutex control thread execution order, 
using the additional control in a thread of execution order;

 
 
  1. /* thread_sem.c */

  2. #include <stdio.h>

  3. #include <stdlib.h>

  4. #include <pthread.h>

  5. #include <semaphore.h>

  6.  
  7. #define THREAD_NUMBER 3

  8. #define REPEAT_NUMBER 3

  9. #define DELAY_TIME_LEVELS 10.0

  10.  
  11. sem_t sem[THREAD_NUMBER];

  12.  
  13. void * thrd_func(void *arg) {

  14. int thrd_num = (int)arg;

  15. int delay_time = 0;

  16. int count = 0;

  17. sem_wait(&sem[thrd_num]);

  18. printf("Thread %d is starting\n", thrd_num);

  19. for (count = 0; count < REPEAT_NUMBER; count++) {

  20. delay_time = (int)(rand() * DELAY_TIME_LEVELS/(RAND_MAX)) + 1;

  21. sleep(delay_time);

  22. printf("\tThread %d: job %d delay = %d\n", thrd_num, count, delay_time);

  23. }

  24. printf("Thread %d finished\n", thrd_num);

  25. pthread_exit(NULL);

  26. }

  27.  
  28. int main(void) {

  29. pthread_t thread[THREAD_NUMBER];

  30. int no = 0, res;

  31. void * thrd_ret;

  32. srand(time(NULL));

  33. for (no = 0; no < THREAD_NUMBER; no++) {

  34. sem_init(&sem[no], 0, 0);

  35. res = pthread_create(&thread[no], NULL, thrd_func, (void*)no);

  36. if (res != 0) {

  37. printf("Create thread %d failed\n", no);

  38. exit(res);

  39. }

  40. }

  41.  
  42. printf("Create treads success\n Waiting for threads to finish...\n");

  43. sem_post(&sem[THREAD_NUMBER - 1]);

  44. for (no = THREAD_NUMBER - 1; no >= 0; no--) {

  45. res = pthread_join(thread[no], &thrd_ret);

  46. if (!res) {

  47. printf("Thread %d joined\n", no);

  48. } else {

  49. printf("Thread %d join failed\n", no);

  50. }

  51. sem_post(&sem[(no + THREAD_NUMBER - 1) % THREAD_NUMBER]);

  52. }

  53.  
  54. for (no = 0; no < THREAD_NUMBER; no++) {

  55. sem_destroy(&sem[no]);

  56. }

  57. return 0;

  58. }


 

  •  

The results still build three threads, each thread to sleep long random execution:

 
 
  1. $ gcc thread_sem.c -lpthread

  2. $ ./a.out

  3. Create treads success

  4. Waiting for threads to finish...

  5. Thread 2 is starting

  6. Thread 2: job 0 delay = 9

  7. Thread 2: job 1 delay = 9

  8. Thread 2: job 2 delay = 5

  9. Thread 2 finished

  10. Thread 2 joined

  11. Thread 1 is starting

  12. Thread 1: job 0 delay = 5

  13. Thread 1: job 1 delay = 7

  14. Thread 1: job 2 delay = 4

  15. Thread 1 finished

  16. Thread 1 joined

  17. Thread 0 is starting

  18. Thread 0: job 0 delay = 3

  19. Thread 0: job 1 delay = 9

  20. Thread 0: job 2 delay = 8

  21. Thread 0 finished

  22. Thread 0 joined


 

  •  

The results of the first two routines are very similar, except that textbooks be executed only in reverse; 
it this way than using a mutex in fact, basically the same amount of code readability comparable;

The basic properties pthread_attr_setscope thread

Properties generally provided: 
a binding property 
separation property 
3 Address Stack 
4 Stack size 
5 Priority

About binding property is bound to a kernel thread; 
separate property mainly whether immediately release the corresponding memory after the talk thread;

 
 
  1. /* thread_attr.c */

  2. #include <stdio.h>

  3. #include <stdlib.h>

  4. #include <pthread.h>

  5.  
  6. #define THREAD_NUMBER 1

  7. #define REPEAT_NUMBER 3

  8. #define DELAY_TIME_LEVELS 10.0

  9. int finish_flag = 0;

  10.  
  11. void * thrd_func(void * arg){

  12. int delay_time = 0;

  13. int count = 0;

  14. printf("Thread is starting\n");

  15. for (count = 0; count < REPEAT_NUMBER; count++) {

  16. delay_time = (int)(rand() * DELAY_TIME_LEVELS/(RAND_MAX)) + 1;

  17. sleep(delay_time);

  18. printf("\tThread : job %d delay = %d\n", count, delay_time);

  19. }

  20. printf("Thread finished\n");

  21. finish_flag = 1;

  22. pthread_exit(NULL);

  23. }

  24.  
  25. int main(void) {

  26. pthread_t thread;

  27. pthread_attr_t attr;

  28. int res = 0;

  29. srand(time(NULL));

  30. res = pthread_attr_init(&attr);

  31. if (res != 0) {

  32. printf("Create attribute failed\n");

  33. exit(res);

  34. }

  35. res = pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);

  36. res += pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);

  37. if (res != 0) {

  38. printf("Setting attribute failed\n");

  39. exit(res);

  40. }

  41. res = pthread_create(&thread, &attr, thrd_func, NULL);

  42. if (res != 0) {

  43. printf("Create thread failed\n");

  44. exit(res);

  45. }

  46. pthread_attr_destroy(&attr);

  47. printf("Create tread success\n");

  48.  
  49. while(!finish_flag){

  50. printf("Waiting for thread to finish...\n");

  51. sleep(2);

  52. }

  53. return 0;

  54. }


 

  •  

Use $ free run commands before and after viewing memory usage before and after the discovery: 
memory is released immediately after the end of the thread; 
in fact, attribute general thread can directly use the system default properties; 
use on threads, nearly so; 
all the routines from : "embedded Linux application development standards tutorial"

Published 136 original articles · won praise 71 · views 160 000 +

Guess you like

Origin blog.csdn.net/u012308586/article/details/104635618