全部博文(1493)
分类:
2012-05-04 08:34:22
原文地址:线程高级操作 之 线程同步(一)使用互斥量 作者:graylocus
在多线程并发执行的环境中就有可能出现冲突操作的情况,使用互斥量能进行线程间的同步,使线程在访问共享资源时受到用户的控制。
1.互斥量的初始化与销毁
互斥量是一种锁,在访问共享资源时对其加锁,在访问结束时释放锁,这样可以保证在任意时间内,只有一个线程处于临界区中。
注:任何想要进入临界区的线程都要对锁进行测试,如果该锁已经被某一个线程所持有,则测试线程就会被阻塞,知道该锁被释放,线程会重复上述过程。
linux环境下使用pthread_mutex_t数据类型表示互斥量,这是一个联合union。
在用户使用互斥量之前要对其进程初始化,使用pthread_mutex_init函数对互斥量进行初始化,
int pthread_mutex_init(pthread_mutex_t *restrict mutex,const pthread_mutexattr *restrict attr)
第一个参数是互斥量的指针,初始化后返回该指针给调用者;第二个参数是互斥量的属性,在此先将该参数设置为NULL,内核会使用默认属性对互斥量进程初始化;
返回值:成功,返回0,;失败返回错误号。
2.得到与释放互斥量
互斥量对用户来说是透明的数据结构,用户不可以直接对其进行操作,而应当使用系统提供的操作互斥量的函数接口。linux环境使用一组函数操作互斥量,得到互斥量,释放互斥量。
int pthread_mutex_lock(pthread_mutex_t *mutex);
int pthread_mutex_trylock(pthread_mutex_t *mutex);
int pthread_mutex_unlock(pthread_mutex_t *mutex);前两个函数用于得到一个互斥量的锁(对临界区加锁),第3个函数用于释放互斥量的锁,对临界区解锁。
pthread_mutex_lock用于获取互斥量的锁,如果该互斥量的锁已经被某一个线程得到,那么该函数会导致线程阻塞,直到互斥量的锁被释放;
成功,返回0,失败返回错误号。
注:pthread_mutex_lock与trylock函数有一点不同,trylock函数在得不到指定互斥量的锁时不会导致线程阻塞,而是立即返回一个错误编号EBUSY,表示所请求的锁处于繁忙状态。这就是trylock的意义,try。
pthread_mutex_unlock用于释放一个互斥量的锁,其参数表示需要释放锁的互斥量。
3.线程同步---使用读写锁
读写锁是另一种线程之间同步的操作,如果没有同步操作,会导致线程在执行时出现与时间有关的错误。
(1)初始化与销毁读写锁
读写锁与互斥量相似,但是并行性更高,原因在于互斥锁每次只有一个线程可以得到锁进行操作,其余的线程阻塞。读写锁的好处是线程根据操作类型分为两类:读线程+写线程。读线程只对共享资源进行读操作,并不改变共享资源;写线程对共享资源进行写操作,会改变共享资源。
因此,对于多个读线程可以共同占有一个读写锁,对于写线程,任意时刻只有一个线程占有。
如果对共享资源做读操作的线程远大于写线程的时候,使用读写锁可以极大的提高线程的并发度。
linux环境下使用pthread_rwlock_t结构类型表示读写锁,在使用读写锁之前要对其进行初始化。
int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock,const pthread_rwlockattr_t *attr);
第一个参数是读写锁的指针,读写锁在该函数内被初始化,并通过该参数返回给调用线程。
第二个参数是读写锁的属性,通常为NULL。
当一个读写锁不再使用时,应将其销毁
int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);
成功销毁返回0,失败返回错误号
(2)得到与释放互斥锁
linux环境下使用一组函数操作在读模式下得到读写锁:
int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock);
参数表示一个读写锁,调用线程希望在读模式下得到该读写锁。如果该读写锁已经被某一个线程在读模式下得到,则测试线程仍然会得到该锁;如果该读写锁已经被某一个线程在写模式下得到,或者有一个线程在写模式下等待该锁,这时pthread_rwlock_rdlock函数会导致线程阻塞,直到读写锁被释放。
trylock在得不到指定读写锁时,并不会导致调用线程阻塞,而是立即返回一个错误编号EBUSY,。
写模式下也有一组得到锁的函数
int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock);
在测试线程读写锁的时候,有任意一个线程占有该锁,wrlock函数就会导致阻塞,并会导致其后所有申请该读写锁的线程阻塞等待。
两种模式下,释放一个读写锁的方式是一样的:
int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);
(3)使用互斥量与读写锁的比较