线程同步的方法
1.线程同步的方法
线程的同步方法有互斥锁、条件变量(cond)、读写锁和POSIX信号量。
2.互斥锁
int pthread_mutex_init(pthread_mutex_t *mutex,const pthread_mutex_attr_t *mutexattr);
初始化互斥锁。
mutexattr的取值范围:
(1)PTHREAD_MUTEX_TIMED_NP,这是缺省值,也就是普通锁。当一个线程加锁以后,其余请求锁的线程将形成一个等待队列,并在解锁后按优先级获得锁。这种锁策略保证了资源分配的公平性。
(2)PTHREAD_MUTEX_RECURSIVE_NP,嵌套锁,允许同一个线程对同一个锁成功获得多次,并通过多次unlock解锁。如果是不同线程请求,则在加锁线程解锁时重新竞争。
(3)PTHREAD_MUTEX_ERRORCHECK_NP,检错锁,如果同一个线程连续加锁两次(死锁),则第二次加锁会立刻返回EDEADLK,否则与PTHREAD_MUTEX_TIMED_NP类型动作相同。
(4)PTHREAD_MUTEX_ADAPTIVE_NP,适应锁,动作最简单的锁类型,仅等待解锁后重新竞争。
检错锁第二次加锁会直接返回EDEADLK(而不是阻塞),这样虽然不会导致死锁,但是明显是有代码问题。
int pthread_mutex_lock(pthread_mutex *mutex);
阻塞加锁。
int pthread_mutex_trylock( pthread_mutex_t *mutex);
非阻塞加锁。
int pthread_mutex_unlock(pthread_mutex *mutex);
解锁。
int pthread_mutex_destroy(pthread_mutex *mutex);
销毁锁。
3.条件变量
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);
定时等待信号。无论哪种等待方式,都必须和一个互斥锁配合,以防止多个线程同时调用等待函数。mutex互斥锁必须是普通锁(PTHREAD_MUTEX_TIMED_NP)或者适应锁(PTHREAD_MUTEX_ADAPTIVE_NP)。
int pthread_cond_signal(pthread_cond_t *cond);
激活单个线程,存在多个线程时,按入队顺序激活第一个。
int pthread_cond_broadcast(pthread_cond_t *cond);
激活所有线程。
int pthread_cond_destroy(pthread_cond_t *cond);
销毁。
4.读写锁
int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock, const pthread_rwlockattr_t *restrict attr);
初始化。
int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_timedrdlock(pthread_rwlock_t *restrict rwlock, const struct timespec *restrict abs_timeout);
加读锁。
int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_timedwrlock(pthread_rwlock_t *restrict rwlock, const struct timespec *restrict abs_timeout);
加写锁。
int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);
销毁锁。
5.POSIX信号量
int sem_init(sem_t *sem, int pshared, unsigned int value);
初始化信号量,其中sem是要初始化的信号量,pshared是0表示此信号量是当前进程的局部信号量,否则这个信号量就可以在多个进程之间共享。value指定信号量的初始值。
int sem_wait(sem_t *sem);
该函数以原子操作的方式将信号量的值减1。如果信号量的值为0,则阻塞等待信号量变为非0值时才返回。
int sem_trywait(sem_t *sem);
非阻塞等待。
int sem_post(sem_t *sem);
该函数以原子操作的方式将信号量的值加1。当信号量的值大于0时,其他调用sem_wait的函数将被唤醒。
int sem_destroy(sem_t *sem);
销毁。
6.问题
问题1:信号量和互斥锁(mutex)的区别:互斥锁只允许一个线程进入临界区,而信号量允许多个线程同时进入临界区。