线程的最大特点是资源的共享性,linux下提供了多种方式来处理线程同步,最常用的是互斥锁、条件变量、信号量、读写锁。

1)互斥锁(mutex)

通过锁机制实现线程间的同步。同一时刻只允许一个线程执行一个关键部分的代码。

int pthread_mutex_init(pthread_mutex_t *mutex,const pthread_mutex_attr_t *mutexattr);

int pthread_mutex_lock(pthread_mutex *mutex);

int pthread_mutex_destroy(pthread_mutex *mutex);

int pthread_mutex_unlock(pthread_mutex *);

(1)先初始化锁init()或静态赋值pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIER

init()函数的参数二有以下四种类型:

PTHREAD_MUTEX_TIMED_NP:其余线程等待队列

PTHREAD_MUTEX_RECURSIVE_NP:嵌套锁,允许线程多次加锁,不同线程,解锁后重新竞争

PTHREAD_MUTEX_ERRORCHECK_NP:检错,与一同,线程请求已用锁,返回EDEADLK;

PTHREAD_MUTEX_ADAPTIVE_NP:适应锁,解锁后重新竞争

(2)加锁,lock,trylock,lock阻塞等待锁,trylock立即返回EBUSY

(3)解锁,unlock需满足是加锁状态,且由加锁线程解锁

(4)清除锁,destroy(此时锁必需unlock,否则返回EBUSY,//Linux下互斥锁不占用内存资源

2)条件变量(cond)

利用线程间共享的全局变量进行同步的一种机制。条件变量上的基本操作有:触发条件(当条件变为 true 时);等待条件,挂起线程直到其他线程触发条件。

  • 常用函数如下:

int pthread_cond_init(pthread_cond_t *cond,pthread_condattr_t *cond_attr);   

int pthread_cond_wait(pthread_cond_t *cond,pthread_mutex_t *mutex);

int pthread_cond_timewait(pthread_cond_t *cond,pthread_mutex *mutex,const timespec *abstime);

int pthread_cond_destroy(pthread_cond_t *cond);

int pthread_cond_signal(pthread_cond_t *cond);

int pthread_cond_broadcast(pthread_cond_t *cond);  //解除所有线程的阻塞

  • 使用流程如下:

(1)初始化.init()或者pthread_cond_t cond=PTHREAD_COND_INITIALIER(前者为动态初始化,后者为静态初始化);属性置为NULL

(2)等待条件成立.pthread_wait,pthread_timewait.wait()释放锁,并阻塞等待条件变量为真,timewait()设置等待时间,仍未signal,返回ETIMEOUT(加锁保证只有一个线程wait)

(3)**条件变量:pthread_cond_signal,pthread_cond_broadcast(**所有等待线程)

(4)清除条件变量:destroy;无线程等待,否则返回EBUSY

  • 说明:

1、pthread_cond_wait、pthread_cond_timewait 的互斥锁区域内使用

2、pthread_cond_wait 自动解锁互斥量(如同执行了pthread_unlock_mutex),并等待条件变量触发。这时线程挂起,不占用CPU时间,直到条件变量被触发(变量为ture)。在调用 pthread_cond_wait之前,应用程序必须加锁互斥量。pthread_cond_wait函数返回前,自动重新对互斥量加锁(如同执行了pthread_lock_mutex)。

3、pthread_cond_destroy 销毁一个条件变量,释放它拥有的资源。进入 pthread_cond_destroy 之前,必须没有在该条件变量上等待的线程。

4、条件变量函数不是异步信号安全的,不应当在信号处理程序中进行调用。特别要注意,如果在信号处理程序中调用 pthread_cond_signal 或pthread_cond_boardcast 函数,可能导致调用线程死锁。

3)线程信号量(无名信号量)

无名信号量不能用进程间通信,用于线程间通信;有名信号量可用于进程和线程,但一般用于进程。

线程信号量(无名信号量)头文件:semaphore.h;

进程信号量(有名信号量)头文件:sys/sem.h。

线程使用的信号量基本函数有四个:

1、int sem_init (sem_t *sem , int pshared, unsigned int value);

对由sem指定的信号量进行初始化,设置好它的共享选项(linux中,sem_init的第二个参数必须为0,表示线程间通信),然后给它一个初始值VALUE。

2、int sem_wait(sem_t *sem); 

原子操作函数,给信号量的值加1,相当于V操作;

3、int sem_post(sem_t *sem); 

原子操作函数,给信号量减1,相当于P操作;对一个值为0的信号量调用sem_wait,这个函数将会等待直到有其它线程使它不再是0为止。

4、int sem_destroy(sem_t *sem);

这个函数的作用是再我们用完信号量后进行清理。归还自己占有的一切资源。

4)读写锁

读写基本原则:

  • 若当前线程读数据,则允许其他线程读数据,但不允许写
  • 若当前线程写数据,则不允许其他线程读、写数据

Linux下C++线程间同步机制

参考链接:https://www.cnblogs.com/Jimmy1988/p/7822478.html 

相关文章:

  • 2021-09-16
  • 2021-06-26
  • 2021-08-14
  • 2022-12-23
  • 2022-12-23
  • 2021-12-18
  • 2022-12-23
猜你喜欢
  • 2021-11-18
  • 2021-11-18
  • 2021-11-18
  • 2021-11-18
  • 2021-06-19
相关资源
相似解决方案