Multithreading | Thread synchronization and thread safety

1.Multi-threading

Threads have a complete set of function library calls related to them, and most of their function names begin with pthread_ . In order to use these function library calls, we must define the macro _REENTRANT , include the header file pthread.h in the program, and link the thread library with the option -lpthread when compiling the program.

-L specifies the storage location of the library

-l specifies the name of the library

Parallel: special concurrent operation, synchronous operation, requiring multiple processors

Concurrency: Alternating execution over a period of time, a single processor can

Note: Having multiple processors is not necessarily parallel or concurrent.

 

2. Thread synchronization

All threads in a process share the same address space and other resources such as open files. Any modification of a resource by one thread will affect the environment of other threads in the same process. Therefore, the activities of various threads need to be synchronized so that they do not interfere with each other and do not destroy data structures. For example, if two threads try to add an element to a doubly linked list at the same time, an element may be lost or the linked list structure may be destroyed.

Thread synchronization means that when a thread is operating on a certain critical resource, other threads cannot operate on this resource. Until the thread completes the operation, other threads can operate, that is, coordinated pace, allowing the threads to operate in a predetermined order. Run in sequence. There are four methods of thread synchronization: mutex locks, semaphores, condition variables, and read-write locks.

2.1 Mutex lock

int pthread_mutex_init(pthread_mutex_t *mutex,pthread_mutexattr_t 
*attr);//attr:锁的属性,不需要传空即可
int pthread_mutex_lock(pthread_mutex_t *mutex);//加锁
int pthread_mutex_unlock(pthread_mutex_t *mutex);//解锁
int pthread_mutex_destroy(pthread_mutex_t *mutex);//销毁锁
//注意,互斥锁mutex都需要传地址,因为要改变它;

2.2 Signal amount

int sem_init(sem_t *sem, int pshared, unsigned int value);
//信号量的初始化
//sem_init()在sem指向的地址初始化未命名的信号量。这个value参数指定信号量的
初始值(第三个参数)。
//pshared:设置信号量是否在进程间共享,Linux不支持,一般给0; (非0为共享)
int sem_wait(sem_t *sem);
//P操作,wait表示等待,相当于是等待获取资源,那么就是P操作
int sem_post(sem_t *sem);
//V操作
int sem_destroy(sem_t *sem);
//销毁信号

2.3 Condition variables

#include <pthread.h>
int pthread_cond_init(pthread_cond_t *cond, pthread_condattr_t
*attr);
int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t
*mutex);
//将条件变量添加到等待队列中,阻塞,等待被唤醒;第一个参数是条件变量的地址,第二个参
数是互斥锁;
//也就是说条件变量往往伴随着互斥锁的使用;
int pthread_cond_signal(pthread_cond_t *cond); //唤醒单个线程
int pthread_cond_broadcast(pthread_cond_t *cond); //唤醒所有等待的
线程
int pthread_cond_destroy(pthread_cond_t *cond);//销毁条件变量

2.4 Read-write lock

Readers and readers share resources, readers and writers are mutually exclusive; writers and writers are mutually exclusive, and writers and readers are mutually exclusive.

#include <pthread.h>
int pthread_rwlock_init(pthread_rwlock_t
*rwlock,pthread_rwlockattr_t *attr);
//第一个参数是锁的地址,第二个参数是锁的属性
int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);//加读锁
int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);//加写锁
int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);//解锁,不管加的
是读锁还是写锁,都用unlock解锁
int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);//销毁

3. Thread safety (key point)

Thread safety means that when multiple threads are running, regardless of the scheduling order of the threads, the final result is the same and correct. Then it is said that these threads are safe.

To ensure thread safety you need to:

1) Thread synchronization ensures that only one thread accesses critical resources at the same time.

2) Use thread-safe functions (reentrant functions) in multi-threads. The so-called thread-safe functions refer to: If a function can be called by multiple threads at the same time without a race condition, then we call it a thread. safe.

Generally speaking: the version of a function with _r is the reentrant version of the function.

Reentrant function: Reentrancy means repeated entry. First of all, it means that this function can be interrupted. Secondly, it means that it does not depend on any environment (including static) except using variables on its own stack. Such a function is purecode ( Pure code) is reentrant, allowing multiple copies of the function to run without interfering with each other because they use separate stacks. If you really need to access global variables (including static), be sure to implement mutual exclusion. Reentrant functions are very important in a parallel running environment, but there is generally some performance penalty for accessing global variables.

Note: In multi-threading, be careful when threads use global (static) variables, because all threads will share these variables, and it is best for threads to use their own local variables.

Threads also have IDs (Linux has a unique way of implementing threads. The kernel does not have the concept of multi-threading and treats threads as processes. The main thread PID is the process PID, and other threads PID + 1)

View method: ps -eLf

Guess you like

Origin blog.csdn.net/weixin_53472334/article/details/132327893