(1)信号量:进化版的互斥量
多个线程间对某个对象的部分数据进行共享,使用互斥锁是没有办法实现的,只能将整个数据对象锁住。这样虽然达到了多线程操作数据共享的目的,却导致线程并发性下降。
信号量:相对折中的一个处理方式,既能保证同步,数据不混乱,又能提高线程开发。
(2)信号量相关函数
sem_t类型,用来定义信号量。虽然是结构体,使用的时候可以当做整数看待(类似文件描述符)。
规定信号量不能小于0,信号量的初值,决定了占用信号量的线程的个数。
头文件在<semaphore.h>
1)初始化一个信号量:sem_init
int sem_init(sem_t *sem,int pshared,unsigned int value);
参数1:信号量
参数2:取0表示线程间共享,取1表示进程间
参数3;信号量初值
2)销毁一个信号量:sem_destroy
int sem_destroy(sem_t *sem);
3)给信号量加锁:sem_wait(信号量初值--)
int sem_wait(sem_t *sem);
4)给信号量解锁:sem_post(信号量初值++)
int sem_post(sem_t *sem);
5)尝试对信号量加锁:sem_trywait
int sem_trywait(sem_t *sem);
6)限时尝试给信号量加锁:sem_timedwait
int sem_timedwait(sem_t *sem,const struct timespec*abs_timeout);
(3)进程间同步
进程间也可以通过互斥锁来达到同步,但必须在pthread_mutex_init初始胡之前,修改其属性为进程间共享。
pthread_mutexattr_t mattr类型,用来定义mutex锁的属性,修改mutex锁属性函数。
1)初始化一个mutex属性对象:pthread_mutexattr_init
int pthread_mutexattr_init(pthread_mutexattr_t *attr);
2)销毁一个mutex属性对象:pthread_mutexattr_destroy
int pthread_mutexattr_destroy(pthread_mutexattr_t *attr);
3)修改mutex属性
int pthread_mutexattr_setpshared(pthread_mutexattr_t *attr , int pshared);
参数2:取值:
线程锁:PTHREAD_PROCESS_PRIVATE(mutex默认属性,进程间私有);
进程锁:PTHREAD_PROCESS_SHARED
(4)使用进程锁完成同步
(5)文件锁
借助fcntl来实现锁机制。操作文件的进程没有获得锁时 ,可以打开,但无法执行read/write操作
fcntl函数:获取和修改文件访问控制属性
int fcntl(int fd,int cmd,.../*arg*/);
参数2:F_SETLK:设置文件锁(trylock)
F_SETLKW 设置文件锁(wait)
F_GETLK 获取文件锁
参数3:
struct flock{
.....
short l_type;//锁的类型:F_RDLCK,F_WRLCK,F_UNLCK(解锁);
short l_whence;//偏移位置,SEEK_SET,SEEK_CUR,SEEK_END
off_t l_start;//起始偏移量
off_t l_len; //加锁数据的长度,len=0,对整个文件加锁
pid_t l_pid;//持有该锁的进程ID:(F_GETLK only)
...
};
(6)进程间文件锁
(7)多线程中,能否使用文件锁?
多线程之间共享文件描述符,而给文件加锁,是通过修改文件描述符所指向的文件结构体中的成员变量来实现的。因此线程之间无法使用文件锁。