Preface
The previous article of
has reviewed the 6 methods of multi -threaded synchronization. Here, the combination of mutual locks and condition variables, and the use of the level of the level.
Taking an interview on the Thunder on the Internet as an example.
1. Topic
Write a program and turn on 3 threads. The IDs of these three threads are A, B, and C.
Each thread prints its ID on the screen 10 times, and the output result must be displayed in the order of ABC; such as: abcabc ....
2. Implementation thinking
-
[1] Can’t just use itmutual lock, because the characteristics of mutual locking are the “disorderly access” of resources
-
[2] Can be usedSoner, the relationship between the three threads forms in turn, and it is notified by the main thread.
-
[3] Usecondition variables, the three threads form a mutually waiting relationship. The available threads waiting for the waiting for notification can be notified by the main thread.
Conditional variables are implemented here.
3. Some thread function prototypes
-
thread creation function: int pthread_create (pthread_t *tid, const pthread_attr_t *attr, void *(void *), void *arg);
-
Waiting thread ending function: int pthread_join (pthread_t tid, void ** ret);
-
Mutual lock initialization function: int pthread_mutex_init (pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr);
-
Mutual lock lock: int pthread_mutex_lock (pthread_mutex_t *mutex);
-
condition variable initialization function: int PTHread_Cond_init (pthread_cond_t *condition, pthread_condattr_t *condattr);
-
condition variable waiting function: int pthread_cond_wait (pthread_cond_t *condition, pthread_mutex_t *latex);
-
condition variable timing waiting function: int pthread_cond_timedwait (pthread_cond_t *condition, pthread_mutex_t *mutex, const struct Timespec *abstime);
-
Condition variable notification function: int PTHread_Cond_SIGNAL (pthread_cond_t *cond);
-
Condition variable broadcast function: int PTHread_Cond_Broidcast (pthread_cond_t *cond);
-
level initialization function: int pthread_barrier_init (pthread_barrier_t *barrier, const pthread_barrierattr_t *attr, unsigned into);
-
level waiting function: int pthread_barrier_wait (pthread_barrier_t *barrier);
4. Code implementation-Use pthread_join ()
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
pthread_t A, B, C; // thread ID
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; // mutual lock, condition variables of mutual exclusion of resources
pthread_cond_t condition = PTHREAD_COND_INITIALIZER; // condition variable
int flag = 0; // Block the threads on the condition of the condition variables, global variables
void *printThread1(void *arg);
void *printThread2(void *arg);
void *printThread3(void *arg);
int main()
{
/*Dynamic initialization method
pthread_mutex_init (& lock, null);
pthread_cond_init (& condition, null);
*/
// Create three sub -threads
int res;
if ((res = pthread_create(&A, NULL, printThread1, NULL)) != 0)
{
printf("Thread A failed to create \ n");
exit(-1);
}
// Conditional placement allows thread 1 to start execution
flag = 1;
if ((res = pthread_create(&B, NULL, printThread2, NULL)) != 0)
{
printf("Thread B failed to create \ n");
exit(-1);
}
if ((res = pthread_create(&C, NULL, printThread3, NULL)) != 0)
{
printf("thread C creation failed \ n");
exit(-1);
}
// Waiting for the end of each sub -thread
pthread_join(A, NULL);
pthread_join(B, NULL);
pthread_join(C, NULL);
// Destroyed mutual lock and condition variables before release of memory
pthread_mutex_destroy(&lock);
pthread_cond_destroy(&condition);
return 0;
}
void *printThread1(void *arg)
{
int i = 0;
while (i < 10)
{
pthread_mutex_lock(&lock);
if (flag != 1) // flag == 1, thread 1 executes
pthread_cond_wait(&condition, &lock);
printf("A");
flag = 2;
i++;
pthread_cond_signal(&condition);
pthread_mutex_unlock(&lock);
}
return NULL; // or Return ((VOID *) 0);
}
void *printThread2(void *arg)
{
int j = 0;
while (j < 10)
{
pthread_mutex_lock(&lock);
if (flag != 2) // flag == 2, thread 2 executes
pthread_cond_wait(&condition, &lock);
printf("B");
flag = 3;
j++;
pthread_cond_signal(&condition);
pthread_mutex_unlock(&lock);
}
return NULL;
}
void *printThread3(void *arg)
{
int k = 0;
while (k < 10)
{
pthread_mutex_lock(&lock);
if (flag != 3) // flag == 3 o'clock, thread 3 executes
pthread_cond_wait(&condition, &lock);
printf("C");
flag = 1;
k++;
pthread_cond_signal(&condition);
pthread_mutex_unlock(&lock);
}
return NULL;
}
Instructions:
[1] Mutual locking and condition variables are created static, so you can choose the method of static initialization (assignment) or dynamic initialization (function)
[2] Previously put the conditional statement flag = 1 after the creation thread was created, and found that sometimes it could run out of the output normally, and sometimes there was no response at all. The problem is that after the thread is created, which one is randomly run. If it is not waiting for the thread 1 condition, it will not continue to run.
[3] pthread_join () There is no order of waiting for different functions, so pthread_join (a, null), pthread_join (b, null), pthread_join (c, null) does not matter who before.
[4] int i, j, k The definitions are placed in various threads instead of as global variables, because the thread is running until the end of the operation, so it can be used as a local variable.
4. Code implementation-Use the level Barriers
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
pthread_t A, B, C; // thread ID
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; // mutual lock, condition variables of mutual exclusion of resources
pthread_cond_t condition = PTHREAD_COND_INITIALIZER; // condition variable
pthread_barrier_t barrier; // level
int flag = 0; // Block the threads on the condition of the condition variables, global variables
void *printThread1(void *arg);
void *printThread2(void *arg);
void *printThread3(void *arg);
int main()
{
// The level is initialized, the number of the number of the sub -thread + 1 (main thread)
pthread_barrier_init(&barrier, NULL, 4);
// Create three sub -threads
int res;
if ((res = pthread_create(&A, NULL, printThread1, NULL)) != 0)
{
printf("Thread A failed to create \ n");
exit(-1);
}
// Conditional placement allows thread 1 to start execution
flag = 1;
if ((res = pthread_create(&B, NULL, printThread2, NULL)) != 0)
{
printf("Thread B failed to create \ n");
exit(-1);
}
if ((res = pthread_create(&C, NULL, printThread3, NULL)) != 0)
{
printf("Thread C Failing Fail \ N");
exit(-1);
}
// Set the thread level, each thread is running to the level
pthread_barrier_wait(&barrier);
// Destroyed mutual lock and condition variables before release of memory
pthread_mutex_destroy(&lock);
pthread_cond_destroy(&condition);
pthread_barrier_destroy(&barrier);
return 0;
}
void *printThread1(void *arg)
{
int i = 0;
while (i < 10)
{
pthread_mutex_lock(&lock);
if (flag != 1)
pthread_cond_wait(&condition, &lock);
printf("A");
flag = 2;
i++;
pthread_cond_signal(&condition);
pthread_mutex_unlock(&lock);
}
pthread_barrier_wait(&barrier);
return NULL;
}
void *printThread2(void *arg)
{
int j = 0;
while (j < 10)
{
pthread_mutex_lock(&lock);
if (flag != 2)
pthread_cond_wait(&condition, &lock);
printf("B");
flag = 3;
j++;
pthread_cond_signal(&condition);
pthread_mutex_unlock(&lock);
}
pthread_barrier_wait(&barrier);
return NULL;
}
void *printThread3(void *arg)
{
int k = 0;
while (k < 10)
{
pthread_mutex_lock(&lock);
if (flag != 3)
pthread_cond_wait(&condition, &lock);
printf("C");
flag = 1;
k++;
pthread_cond_signal(&condition);
pthread_mutex_unlock(&lock);
}
pthread_barrier_wait(&barrier);
return NULL;
}
pthread_cond_wait()function description:
[1] After the mutual lock and run to the condition if (flag! = 1), the thread is blocked in the condition variable
[2] pthread_cond_wait () will be unlocked inside, and then wait for the condition variables to be activated by other threads
[3] After being activated, it will be automatically locked (after other threads release each other)
[4] and re -determine whether the condition variable blocking conditions are established, the establishment of the establishment is re -hanging, and the implementation will continue to execute
Acknowledgements:
http://blog.csdn.net/ithomer/article/details/6031723
http://blog.csdn.net/freedom8531/article/details/45419149
2017.08.31