互斥锁实现线程互斥
- 互斥锁的概念
- 互斥锁的函数
- 示例代码
互斥锁的概念
互斥锁(Mutex)是一种用于多线程编程的同步原语(synchronization primitive),用于实现线程之间的互斥访问共享资源。互斥锁提供了一种机制,确保在任何给定时间点只有一个线程可以访问临界区(Critical Section)。
临界区是指一段代码或数据,它被多个线程共享,并且在任何给定时间只能由一个线程执行或访问,以避免竞争条件(Race Condition)和数据不一致的问题。
互斥锁具备两种状态:已锁定(locked)和未锁定(unlocked)。当一个线程获得了互斥锁的锁定状态时,其他试图获取该互斥锁的线程将被阻塞,直到持有锁的线程释放互斥锁。
互斥锁的常见操作包括两个主要函数:
-
加锁(Lock):当一个线程进入临界区前,通过调用加锁函数来获取互斥锁的锁定状态。如果互斥锁已经被其他线程锁定,那么当前线程将被阻塞,直到互斥锁可用。
-
解锁(Unlock):当一个线程执行完临界区的代码后,通过调用解锁函数来释放互斥锁,使其变为未锁定状态,从而允许其他线程获取该锁。
互斥锁的作用是确保在临界区内只有一个线程在执行,从而保证共享资源的正确性和一致性。当多个线程需要访问共享资源时,通过使用互斥锁来对临界区进行保护,可以有效避免数据竞争和并发访问问题,保证线程安全性。
需要注意的是,互斥锁并不保证公平性,即无法确保线程获取锁的顺序。因此,在编写多线程程序时,应谨慎设计临界区的大小和持锁时间,以避免潜在的性能问题和死锁(Deadlock)情况的发生。
互斥锁的函数
使用互斥锁(Mutex)需要调用一系列相关函数来进行初始化、加锁、解锁和销毁等操作。下面是互斥锁相关函数的详细解释:
-
pthread_mutex_init(pthread_mutex_t* mutex, const pthread_mutexattr_t* attr)
- 该函数用于初始化互斥锁。
- 参数:
mutex
:指向要初始化的互斥锁变量的指针。attr
:指向互斥锁属性的指针,通常为NULL
,表示使用默认属性。
- 返回值:若成功则返回0,否则返回错误码。
-
pthread_mutex_lock(pthread_mutex_t* mutex)
- 该函数用于加锁互斥锁。
- 参数:
mutex
:指向要加锁的互斥锁变量的指针。
- 返回值:若成功则返回0,否则返回错误码。如果互斥锁已经被锁定,调用线程将被阻塞,直到互斥锁可用。
-
pthread_mutex_unlock(pthread_mutex_t* mutex)
- 该函数用于解锁互斥锁。
- 参数:
mutex
:指向要解锁的互斥锁变量的指针。
- 返回值:若成功则返回0,否则返回错误码。如果调用该函数时线程没有持有互斥锁,将导致未定义的行为。
-
pthread_mutex_trylock(pthread_mutex_t* mutex)
- 该函数尝试加锁互斥锁,如果互斥锁已经被锁定,则立即返回失败,不会阻塞线程。
- 参数:
mutex
:指向要尝试加锁的互斥锁变量的指针。
- 返回值:若成功则返回0,表示已经获得互斥锁;若失败则返回
EBUSY
,表示互斥锁已经被锁定。
-
pthread_mutex_destroy(pthread_mutex_t* mutex)
- 该函数用于销毁互斥锁。
- 参数:
mutex
:指向要销毁的互斥锁变量的指针。
- 返回值:若成功则返回0,否则返回错误码。销毁一个正在被其他线程锁定的互斥锁是未定义的行为。
这些函数都需要包含头文件pthread.h
。在使用互斥锁时,通常需要定义一个pthread_mutex_t
类型的变量作为互斥锁对象,并在适当的位置调用上述函数来进行初始化、加锁、解锁和销毁操作,以确保线程的互斥访问和共享资源的正确性。
示例代码
以下是一个使用互斥锁实现线程互斥的示例:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
// 全局变量作为共享资源
int shared_variable = 0;
pthread_mutex_t mutex; // 定义互斥锁
// 线程函数
void* thread_function(void* arg) {
int i;
for (i = 0; i < 1000000; i++) {
pthread_mutex_lock(&mutex); // 加锁
// 访问共享资源
shared_variable++;
pthread_mutex_unlock(&mutex); // 解锁
}
return NULL;
}
int main() {
pthread_t thread1, thread2;
// 初始化互斥锁
pthread_mutex_init(&mutex, NULL);
// 创建线程
pthread_create(&thread1, NULL, thread_function, NULL);
pthread_create(&thread2, NULL, thread_function, NULL);
// 等待线程结束
pthread_join(thread1, NULL);
pthread_join(thread2, NULL);
// 销毁互斥锁
pthread_mutex_destroy(&mutex);
// 输出结果
printf("Shared variable value: %d\n", shared_variable);
return 0;
}
在上面的示例中,使用了pthread_mutex_t
类型的变量mutex
来表示互斥锁。在thread_function
线程函数中,首先使用pthread_mutex_lock
函数对互斥锁进行加锁操作,以确保只有一个线程可以访问临界区(在这里是shared_variable
)。然后,在访问完共享资源后,使用pthread_mutex_unlock
函数对互斥锁进行解锁操作。
在main
函数中,创建了两个线程thread1
和thread2
,它们会并发地访问临界区。最后,使用pthread_join
函数等待线程结束,并在程序最后输出shared_variable
的值。
通过使用互斥锁,可以确保线程对共享资源的互斥访问,从而避免竞争条件和数据不一致的问题。