Talk C chestnuts together (116th back: C language instance -- mutex of thread synchronization 2)
Hello, everyone. The last time we talked about the semaphore of thread synchronization, we will continue to talk about this example. When you leave the rest of your time, your words will go right. Let's talk C chestnuts together!
We described in detail the usage of mutex-related functions in the last time. In this time, we introduced how to use these functions to operate mutex.
The procedure is as follows:
1. defines A mutex A to synchronize threads. 2. use the pthread_mutex_init function in the process of creating a thread to initialize the mutex. The default value is used for the mutex attribute. 3. to read data from the Data Reading thread, use the pthread_mutex_lock function to lock mutex A. Then read the data and use the pthread_mutex_unlock function to unlock mutex A. 4. to modify data in the data writing thread, use the pthread_mutex_lock function to lock mutex A. Then modify the data and use the pthread_mutex_unlock function to unlock mutex A. 5. use the pthread_mutex_destroy function in the thread creation process to release resources related to mutex;
The readers will not write the code in the text, and the detailed code will be put into my resources. You can download and use it.
The code we write is modified based on the mutex code of the semaphores, but we use mutex in the code to replace the semaphores. The function that reads/writes data in the Code is self-implemented to facilitate the description of the problem. Both functions use delayed operations, it takes some time to read or write data.
This may occur when the program is running:
If the read operation is not completed, the write operation is started. This will cause the data read by the read operation to be inaccurate. If the write operation is not completed, the read operation will begin, this will result in inaccurate data read by the read operation;
Below isRunning result of the program when no mutex is usedFor more information, see:
Create first thread // Create the first thread Create second Thread // Create the second thread ID :: 3076062016 ----------- S ---------- [Thread_1] start reading data // The first Thread starts to read data (the first operation on data is a read operation) Thread ID :: 3067669312 ----------- S ---------- [Thread_2] start writing data // The second thread starts to modify data [Thread_1] data = 0 // The first thread reads the initial value of shared data [Thread_1] end reading data [Thread_2] data = 1 // The second thread modifies the shared data [Thread_2] end writing data [Thread_2] start writing data [Thread_1] start reading data [Thread_2] data = 2 [Thread_2] end writing data [Thread_1] data = 2 [Thread_1] end reading data [Thread_2] start writing data [Thread_2] data = 3 [Thread_2] end writing data [thread_1] start reading data [Thread_2] start writing data [Thread_1] data = 3 [Thread_1] end reading data [Thread_2] data = 4 [Thread_2] end writing data Thread ID:: 3067669312 ----------- E ---------- // The second Thread ends [Thread_1] start reading data [Thread_1] data = 4 [Thread_1] end reading data Thread ID :: 3076062016 ----------- E ---------- // The End of the first thread
From the above results, we can see that the second thread has not finished writing data, and the first thread starts reading data, and reads the shared data initialization value. It can be seen that the value he reads is not the data modified by the second thread, or the data is not accurate. Next, the threads reading data run alternately with the threads modifying data, so the thread running sequence is incorrect. It can be seen that if synchronization is not performed on threads, operations on shared data will generate incorrect results.
Below isThe running result of the program after the mutex is used to synchronize the threadFor more information, see:
Create first thread // Create the first thread Create second Thread // Create the second thread ID :: 3075980096 ----------- S ---------- [Thread_1] start reading data // The first Thread starts to read data (the first operation on data is a read operation) Thread ID :: 3067587392 ----------- S ---------- [Thread_1] data = 0 // The first thread reads the initial value of the shared data [Thread_1] end reading data // The first thread reads the shared data and ends [Thread_2] start writing data // The second thread begins to modify the value of shared data [Thread_2] data = 1 // The second thread modifies the value of shared data [Thread_2] end writing data // the second thread modifies the shared data and ends [Thread_1] start reading data // The first thread starts to read the value of the shared data [Thread_1] data = 1 // The first thread reads the correct share data value [Thread_1] end reading data // The first thread reads the shared data end [Thread_2] start writing data [Thread_2] data = 2 [Thread_2] end writing data [Thread_1] start reading data [Thread_1] data = 2 [Thread_1] end reading data [Thread_2] start writing data [Thread_2] data = 3 [Thread_2] end writing data [Thread_1] start reading data [Thread_1] data = 3 [Thread_1] end reading data [Thread_2] start writing data [Thread_2] data = 4 [Thread_2] end writing data Thread ID:: 3075980096 ----------- E ---------- // The first Thread Ends Thread ID: 3067587392 ----------- E ---------- // The second Thread ends
From the above results, we can see that the first thread starts to read data, and the second thread starts to modify data after reading data. At this time, the first thread is in the waiting state, it is not until the second thread completes data modification before it starts to read data, it reads accurate shared data. Next, the Data Reading thread and the data modification thread run in sequence. It can be seen that the operation order for the shared data is correct after the synchronization operation on the thread, and the value read from the shared data is also correct. In addition, compare the synchronization operations on threads using semaphores. The first operation on shared data is a write operation, while the first operation on shared data is a read operation when a mutex is used to synchronize threads. Normally, you must modify the data before you can read the data. It can be seen that the semaphores are more strict on the running sequence of threads.
Based on our experience, semaphores are often used to count or have strict requirements on the sequence, while mutex is often used to access shared resources. Of course, when synchronizing threads, you can choose semaphores and mutex based on your own needs and program requirements.
Let's talk about the mutex of thread synchronization. I want to know what examples will be provided later, and I will try again.