A case of using multithreading to realize ticket purchase. There are 3 windows, a total of 100 tickets
Version 1: The problem of thread synchronization is not considered, and there will be situations where multiple windows buy the same ticket
*/ #include <stdio.h> #include <pthread.h> #include <unistd.h> // Global variables, all threads share this resource. int tickets = 100; void * sellticket(void * arg) {<!-- --> // sell tickets while(tickets > 0) {<!-- --> usleep(6000); printf("%ld is selling %d tickets\\ ", pthread_self(), tickets); tickets--; } return NULL; } int main() {<!-- --> // Create 3 child threads pthread_t tid1, tid2, tid3; pthread_create( &tid1, NULL, sellticket, NULL); pthread_create( & tid2, NULL, sellticket, NULL); pthread_create( & tid3, NULL, sellticket, NULL); // Recycle the resources of the child thread, blocking pthread_join(tid1, NULL); pthread_join(tid2, NULL); pthread_join(tid3, NULL); // Set thread detachment. //pthread_detach(tid1); //pthread_detach(tid2); //pthread_detach(tid3); pthread_exit(NULL); // exit the main thread return 0; }
Version 2: Add mutex to achieve synchronization, avoiding the above mistakes
type of mutex pthread_mutex_t int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr); - Initialize the mutex - parameters: - mutex: the mutex variable that needs to be initialized - attr: Mutex-related attributes, NULL - restrict : A modifier of the C language, the modified pointer cannot be operated by another pointer. pthread_mutex_t *restrict mutex = xxx; pthread_mutex_t * mutex1 = mutex; int pthread_mutex_destroy(pthread_mutex_t *mutex); - release mutex resources int pthread_mutex_lock(pthread_mutex_t *mutex); - Locking, blocking, if one thread is locked, then other threads can only block and wait int pthread_mutex_trylock(pthread_mutex_t *mutex); - Try to lock. If the lock fails, it will not block and return directly. int pthread_mutex_unlock(pthread_mutex_t *mutex); - unlock */ #include <stdio.h> #include <pthread.h> #include <unistd.h> // Global variables, all threads share this resource. int tickets = 1000; // create a mutex pthread_mutex_t mutex; void * sellticket(void * arg) {<!-- --> // sell tickets while(1) {<!-- --> // lock pthread_mutex_lock( & mutex); if(tickets > 0) {<!-- --> usleep(6000); printf("%ld is selling %d tickets\\ ", pthread_self(), tickets); tickets--; } else {<!-- --> // unlock pthread_mutex_unlock( & mutex); break; } // unlock pthread_mutex_unlock( & mutex); } return NULL; } int main() {<!-- --> // Initialize the mutex pthread_mutex_init( & mutex, NULL); // Create 3 child threads pthread_t tid1, tid2, tid3; pthread_create( &tid1, NULL, sellticket, NULL); pthread_create( & tid2, NULL, sellticket, NULL); pthread_create( & tid3, NULL, sellticket, NULL); // Recycle the resources of the child thread, blocking pthread_join(tid1, NULL); pthread_join(tid2, NULL); pthread_join(tid3, NULL); pthread_exit(NULL); // exit the main thread // Release the mutex resource pthread_mutex_destroy( & mutex); return 0; }
The first two are relatively simple, no demonstration, mainly demonstrate the third one
#include <stdio.h> #include <pthread.h> #include <unistd.h> // Create 2 mutexes pthread_mutex_t mutex1, mutex2; void * workA(void * arg) {<!-- --> pthread_mutex_lock( & mutex1); sleep(1); pthread_mutex_lock( & mutex2); printf("workA....\\ "); pthread_mutex_unlock( & mutex2); pthread_mutex_unlock( & mutex1); return NULL; } void * workB(void * arg) {<!-- --> pthread_mutex_lock( & mutex2); sleep(1); pthread_mutex_lock( & mutex1); printf("workB....\\ "); pthread_mutex_unlock( & mutex1); pthread_mutex_unlock( & mutex2); return NULL; } int main() {<!-- --> // Initialize the mutex pthread_mutex_init( & mutex1, NULL); pthread_mutex_init( & mutex2, NULL); // Create 2 child threads pthread_t tid1, tid2; pthread_create( & tid1, NULL, workA, NULL); pthread_create( & tid2, NULL, workB, NULL); // Recycle child thread resources pthread_join(tid1, NULL); pthread_join(tid2, NULL); // Release the mutex resource pthread_mutex_destroy( & mutex1); pthread_mutex_destroy( & mutex2); return 0; }
The type of read-write lock pthread_rwlock_t 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_tryrdlock(pthread_rwlock_t *rwlock); int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock); int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock); int pthread_rwlock_unlock(pthread_rwlock_t *rwlock); Case: 8 threads operate the same global variable. 3 threads write this global variable from time to time, and 5 threads read this global variable from time to time */ #include <stdio.h> #include <pthread.h> #include <unistd.h> // Create a shared data int num = 1; // pthread_mutex_t mutex; pthread_rwlock_t rwlock; void * writeNum(void * arg) {<!-- --> while(1) {<!-- --> pthread_rwlock_wrlock( & amp; rwlock); num++; printf(" + + write, tid : %ld, num : %d\\ ", pthread_self(), num); pthread_rwlock_unlock( & rwlock); usleep(100); } return NULL; } void * readNum(void * arg) {<!-- --> while(1) {<!-- --> pthread_rwlock_rdlock( & rwlock); printf("===read, tid : %ld, num : %d\\ ", pthread_self(), num); pthread_rwlock_unlock( & rwlock); usleep(100); } return NULL; } int main() {<!-- --> pthread_rwlock_init( & rwlock, NULL); // Create 3 write threads and 5 read threads pthread_t wtids[3], rtids[5]; for(int i = 0; i < 3; i ++ ) {<!-- --> pthread_create( &wtids[i], NULL, writeNum, NULL); } for(int i = 0; i < 5; i ++ ) {<!-- --> pthread_create( &rtids[i], NULL, readNum, NULL); } // set thread separation for(int i = 0; i < 3; i ++ ) {<!-- --> pthread_detach(wtids[i]); } for(int i = 0; i < 5; i ++ ) {<!-- --> pthread_detach(rtids[i]); } pthread_exit(NULL); pthread_rwlock_destroy( & rwlock); return 0; }