一、互斥锁
在编程中,引入了对象互斥锁的概念,来保证共享数据操作的完整性。每个对象都对应于一个可称为" 互斥锁" 的标记,这个标记用来保证在任一时刻,只能有一个线程访问该对象。
互斥锁(又名互斥量)强调的是资源的访问互斥:互斥锁是用在多线程多任务互斥的,一个线程占用了某一个资源,那么别的线程就无法访问,直到这个线程unlock,其他的线程才开始可以利用这个资源。
1. 创建互斥锁
互斥锁的创建方式有两种:静态方式和动态方式
- 静态方式
POSIX定义了一个宏PTHREAD_MUTEX_INITIALIZER来静态初始化互斥锁,方法如下:
pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER
- 动态方式
动态方式是采用pthread_mutex_init()函数来初始化互斥锁,API定义如下:
int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr)
其中mutexattr用于指定互斥锁属性,如果为NULL则使用缺省属性。
2. 销毁锁
函数原型:int pthread_mutex_destroy(pthread_mutex_t *mutex)
销毁一个互斥锁即意味着释放它所占用的资源,且要求锁当前处于开放状态。由于在Linux中,互斥锁并不占用任何资源,因此LinuxThreads中的 pthread_mutex_destroy()除了检查锁状态以外(锁定状态则返回EBUSY)没有其他动作。
3. 锁操作
- 加锁:
int pthread_mutex_lock(pthread_mutex_t *mutex)
- 解锁:
int pthread_mutex_unlock(pthread_mutex_t *mutex)
- trylock:
int pthread_mutex_trylock(pthread_mutex_t *mutex)
pthread_mutex_trylock()语义与pthread_mutex_lock()类似,不同的是在锁已经被占据时返回EBUSY而不是挂起等待。
二、Demo
两个线程分别交替打印"hello world"、“HELLO WORLD”:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
pthread_mutex_t mutex; //定义一把互斥锁
void *tfn(void *arg)
{
srand(time(NULL));
while(1)
{
pthread_mutex_lock(&mutex);
printf("hello ");
sleep(rand() % 3); //模拟长时间操作共享资源,导致cpu易主,产生与时间有关的错误
printf("world\n");
pthread_mutex_unlock(&mutex);
sleep(rand() % 3);
}
return NULL;
}
int main(void)
{
pthread_t tid;
srand(time(NULL));
int ret = pthread_mutex_init(&mutex, NULL); //动态方式初始化互斥锁
if(ret != 0)
{
fprintf(stderr, "mutex_init error: %s\n", strerror(ret));
exit(1);
}
pthread_create(&tid, NULL, tfn, NULL);
while(1)
{
pthread_mutex_lock(&mutex);
printf("HELLO ");
sleep(rand() % 3); //模拟长时间操作共享资源,导致cpu易主,产生与时间有关的错误
printf("WORLD\n");
pthread_mutex_unlock(&mutex);
sleep(rand() % 3);
}
pthread_join(tid, NULL);
pthread_mutex_destroy(&mutex); //销毁互斥锁
return 0;
}
参考资料:
互斥锁_百度百科