linux 线程互斥锁

本文介绍如何利用互斥锁实现线程间的同步。包括互斥锁的创建、属性设置、释放及基本操作等核心内容,并通过示例代码演示互斥锁的实际应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在线程实际运行过程中,我们经常需要多个线程保持同步。这时可以用互斥锁来完成任务;互斥锁的使用过程中,主要有pthread_mutex_init,pthread_mutex_destory,pthread_mutex_lock,pthread_mutex_unlock这几个函数以完成锁的初始化,锁的销毁,上锁和释放锁操作。


一,锁的创建

    锁可以被动态或静态创建,可以用宏PTHREAD_MUTEX_INITIALIZER来静态的初始化锁,采用这种方式比较容易理解,互斥锁是pthread_mutex_t的结构体,而这个宏是一个结构常量,如下可以完成静态的初始化锁:

    pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

    另外锁可以用pthread_mutex_init函数动态的创建,函数原型如下:

    int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t * attr)

二,锁的属性

    互斥锁属性可以由pthread_mutexattr_init(pthread_mutexattr_t *mattr);来初始化,然后可以调用其他的属性设置方法来设置其属性;

    互斥锁的范围:可以指定是该进程与其他进程的同步还是同一进程内不同的线程之间的同步。可以设置为PTHREAD_PROCESS_SHARE和PTHREAD_PROCESS_PRIVATE。默认是后者,表示进程内使用锁。可以使用int pthread_mutexattr_setpshared(pthread_mutexattr_t *mattr, int pshared)

pthread_mutexattr_getshared(pthread_mutexattr_t *mattr,int *pshared)

用来设置与获取锁的范围;

    互斥锁的类型:有以下几个取值空间:

  PTHREAD_MUTEX_TIMED_NP,这是缺省值,也就是普通锁。当一个线程加锁以后,其余请求锁的线程将形成一个等待队列,并在解锁后按优先级获得锁。这种锁策略保证了资源分配的公平性。

  PTHREAD_MUTEX_RECURSIVE_NP,嵌套锁,允许同一个线程对同一个锁成功获得多次,并通过多次unlock解锁。如果是不同线程请求,则在加锁线程解锁时重新竞争。

  PTHREAD_MUTEX_ERRORCHECK_NP,检错锁,如果同一个线程请求同一个锁,则返回EDEADLK,否则与PTHREAD_MUTEX_TIMED_NP类型动作相同。这样就保证当不允许多次加锁时不会出现最简单情况下的死锁。

  PTHREAD_MUTEX_ADAPTIVE_NP,适应锁,动作最简单的锁类型,仅等待解锁后重新竞争。

可以用
pthread_mutexattr_settype(pthread_mutexattr_t *attr , int type)
pthread_mutexattr_gettype(pthread_mutexattr_t *attr , int *type)

获取或设置锁的类型。

三,锁的释放

    调用pthread_mutex_destory之后,可以释放锁占用的资源,但这有一个前提上锁当前是没有被锁的状态。

四,锁操作

    对锁的操作主要包括加锁 pthread_mutex_lock()、解锁pthread_mutex_unlock()和测试加锁 pthread_mutex_trylock()三个。

  int pthread_mutex_lock(pthread_mutex_t *mutex)

  int pthread_mutex_unlock(pthread_mutex_t *mutex)

  int pthread_mutex_trylock(pthread_mutex_t *mutex)

  pthread_mutex_trylock()语义与pthread_mutex_lock()类似,不同的是在锁已经被占据时返回EBUSY而不是挂起等待

五,锁的使用

[cpp]  view plain copy
  1. #include <pthread.h>  
  2. #include <stdio.h>  
  3.   
  4. pthread_mutex_t mutex ;  
  5. void *print_msg(void *arg){  
  6.         int i=0;  
  7.         pthread_mutex_lock(&mutex);  
  8.         for(i=0;i<15;i++){  
  9.                 printf("output : %d\n",i);  
  10.                 usleep(100);  
  11.         }  
  12.         pthread_mutex_unlock(&mutex);  
  13. }  
  14. int main(int argc,char** argv){  
  15.         pthread_t id1;  
  16.         pthread_t id2;  
  17.         pthread_mutex_init(&mutex,NULL);  
  18.         pthread_create(&id1,NULL,print_msg,NULL);  
  19.         pthread_create(&id2,NULL,print_msg,NULL);  
  20.         pthread_join(id1,NULL);  
  21.         pthread_join(id2,NULL);  
  22.         pthread_mutex_destroy(&mutex);  
  23.         return 1;  
  24. }  
将会一个线程一个线程的执行。
### Linux 环境下线程互斥锁 `pthread_mutex` 的使用 在 Linux 编程环境中,`pthread_mutex_t` 是用于实现多线程间同步的一种机制。它通过提供加锁和解锁功能来保护共享资源免受并发访问的影响。 #### 初始化互斥锁 可以通过两种方式初始化互斥锁: 1. **静态初始化** 使用 `PTHREAD_MUTEX_INITIALIZER` 对互斥锁进行静态初始化。这种方式适用于全局变量或静态变量的场景。 ```c pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; ``` 2. **动态初始化** 调用函数 `pthread_mutex_init()` 动态创建并初始化互斥锁。此方法允许指定额外的属性参数(通常设置为 NULL 表示默认属性)。 ```c pthread_mutex_t mutex; int result = pthread_mutex_init(&mutex, NULL); if (result != 0) { perror("Mutex initialization failed"); exit(EXIT_FAILURE); } ``` #### 加锁与解锁操作 为了确保多个线程不会同时访问同一段临界区代码,在进入该区域前需调用 `pthread_mutex_lock()` 或其非阻塞版本 `pthread_mutex_trylock()` 进行锁定;完成工作后应立即释放锁以避免死锁情况发生。 - **加锁** ```c int lock_result = pthread_mutex_lock(&mutex); if(lock_result != 0){ perror("Failed to acquire the lock."); // Handle error appropriately. } ``` - **尝试加锁(非阻塞)** 如果当前无法获取到锁,则返回错误码而不是等待。 ```c int trylock_result = pthread_mutex_trylock(&mutex); if(trylock_result == EBUSY){ printf("Lock is busy.\n"); }else{ // Proceed with critical section... } ``` - **解锁** 当前线程结束对共享数据的操作之后应当及时解除对该对象上的任何控制权以便其他可能正在排队等候它的进程可以继续运行下去。 ```c int unlock_result = pthread_mutex_unlock(&mutex); if(unlock_result != 0){ perror("Unlocking mutex failed."); // Error handling code here as needed. } ``` #### 销毁互斥锁 当不再需要某个特定类型的互斥体实例时应该销毁它们从而回收内存空间以及减少不必要的开销。 ```c int destroy_result = pthread_mutex_destroy(&mutex); if(destroy_result != 0){ perror("Destroying mutex encountered an issue."); } ``` 以下是完整的例子展示如何在线程之间安全地更新计数器值: ```c #include <stdio.h> #include <stdlib.h> #include <pthread.h> // Define global variables and initialize them properly. long counter = 0L; pthread_mutex_t count_mutex; void* increase_counter(void* arg){ long i; for(i=0;i<1000000;i++){ pthread_mutex_lock(&count_mutex); // Lock before modifying shared resource. counter +=1 ; pthread_mutex_unlock(&count_mutex); // Unlock after modification finished. } return NULL; } int main(){ pthread_t thread_one,thread_two; /* Initialize Mutex */ if(pthread_mutex_init(&count_mutex,NULL)!=0){ fprintf(stderr,"Error initializing mutex\n"); return EXIT_FAILURE; } /* Create threads that will increment our counter variable safely using locks.*/ if(pthread_create(&thread_one,NULL,increase_counter,(void*)NULL)){ fprintf(stderr,"Thread creation failed!\n"); goto cleanup_mutex; } if(pthread_create(&thread_two,NULL,increase_counter,(void*)NULL)){ fprintf(stderr,"Second Thread Creation Failed!"); goto join_first_thread; } /* Wait until both threads finish their job*/ pthread_join(thread_one,NULL); join_first_thread: pthread_join(thread_two,NULL); cleanup_mutex: pthread_mutex_destroy(&count_mutex); printf("Final Counter Value:%ld\n",counter); return EXIT_SUCCESS; } ``` 上述程序展示了两个独立工作的线程共同增加同一个整型数值的过程,并且每次修改之前都会先获得相应的互斥锁,这样就防止了竞争条件的发生。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值