当前位置:首页 > 技术知识 > 正文内容

C语言编写多线程,什么时候要使用互斥锁?为什么要使用互斥锁?

maynowei10个月前 (08-03)技术知识167

在多线程编程中,当多个线程同时访问共享资源(如变量、文件等)时,会出现竞态条件(Race Condition)问题,导致程序的行为不可预测。为了避免这种问题,需要使用互斥锁来保护共享资源的访问。

互斥锁是一种线程同步机制,它保证同一时刻只有一个线程可以访问共享资源,其他线程需要等待该线程释放锁才能继续访问。在C语言中,可以使用标准库提供的pthread_mutex_t结构体来实现互斥锁。

在哪些情况下需要使用互斥锁呢?一般来说,只有在多个线程同时访问共享资源时才需要使用互斥锁。以下是一些常见的情况:

  1. 多个线程同时访问同一个全局变量或静态变量。
  2. 多个线程同时访问同一个动态分配的内存块。
  3. 多个线程同时访问同一个文件或网络套接字。
  4. 多个线程同时访问同一个数据结构,如链表或树。

需要注意的是,过多地使用互斥锁可能会导致性能问题。因此,在使用互斥锁时,需要权衡程序的正确性和性能开销,尽可能减少锁的使用次数。

假设有两个线程 A 和 B,它们需要同时访问一个共享资源:一个全局变量 x。线程 A 需要读取 x 的值并将其加 1,线程 B 需要读取 x 的值并将其减 1。

如果不使用互斥锁,可能会出现以下情况:

  1. 线程 A 读取 x 的值为 n,然后将其加 1,得到 n+1。
  2. 在线程 A 执行完加 1 操作之前,线程 B 读取 x 的值为 n,然后将其减 1,得到 n-1。
  3. 线程 A 将 n+1 写回到 x 中,x 的值变成了 n+1。
  4. 线程 B 将 n-1 写回到 x 中,x 的值变成了 n-1,而不是原本的 n。

为了避免这种竞态条件问题,可以使用互斥锁来保护 x 的访问。具体地,在访问 x 的代码前加锁,在访问结束后释放锁。这样可以保证同一时刻只有一个线程可以访问 x,从而避免竞态条件问题。

下面是一个简单的C语言使用互斥锁保护全局变量的例子:

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;  // 定义互斥锁

int global_var = 0;

void *thread_func(void *arg) {
    int thread_num = *(int *)arg;
    int i;
    for (i = 0; i < 100000; i++) {
        pthread_mutex_lock(&mutex);  // 加锁
        global_var++;
        printf("Thread %d: global_var = %d\n", thread_num, global_var);
        pthread_mutex_unlock(&mutex);  // 解锁
    }
    return NULL;
}

int main() {
    pthread_t thread1, thread2;
    int thread_num1 = 1, thread_num2 = 2;

    // 创建两个线程
    if (pthread_create(&thread1, NULL, thread_func, &thread_num1) != 0) {
        perror("pthread_create");
        exit(EXIT_FAILURE);
    }
    if (pthread_create(&thread2, NULL, thread_func, &thread_num2) != 0) {
        perror("pthread_create");
        exit(EXIT_FAILURE);
    }

    // 等待两个线程结束
    if (pthread_join(thread1, NULL) != 0) {
        perror("pthread_join");
        exit(EXIT_FAILURE);
    }
    if (pthread_join(thread2, NULL) != 0) {
        perror("pthread_join");
        exit(EXIT_FAILURE);
    }

    return 0;
}

在上面的代码中,我们定义了一个全局变量 global_var,然后创建了两个线程 thread1 和 thread2,它们会分别对 global_var 进行加 1 操作。在访问 global_var 的代码前,我们使用了 pthread_mutex_lock 函数来加锁,在访问结束后使用 pthread_mutex_unlock 函数来解锁,以保证同一时刻只有一个线程可以访问 global_var。

相关文章

事半功倍 轻松制作可交互移动原型

写在前面先讲个场景,看看有多少人躺枪,你在一个没有专职的交互设计师的公司做客户端的产品,基本上产品和交互的活儿你全承包了,当你准备好一切需要向领导和项目团队一起讲新版本的设计:做过WEB产品的老手,或...

CPU「离奇」飙到 100%!开发者挖出 Linux 内核 16 年老 Bug:这么多年竟无人发现?

【CSDN 编者按】每一次对旧设备的升级都仿佛是一场跨越时代的冒险。本文作者致力于将基于 PXA166 的 Chumby 8 设备从 Linux 2.6.28 版本升级到现代 6.x 版本,然而,在看...

centos系统安装oracle简易客户端instantclient

一、目录1:centos 环境准备2:instant client 下载3:instant client 安装4:instant client 配置5:测试连接二、安装步骤1:zip,unzip命令安...

ORA-12514 TNS 监听程序当前无法识别连接描述符中请求服务

早上同事用PL/SQL连接虚拟机中的Oracle数据库,发现又报了“ORA-12514 TNS 监听程序当前无法识别连接描述符中请求服务”错误,帮其解决后,发现很多人遇到过这样的问题,因此写着这里。也...

分享收藏的 oracle 11.2.0.4各平台的下载地址

概述oracle 11.2.0.4是目前生产环境用的比较多的版本,同时也是很稳定的一个版本。目前官网上已经找不到下载链接了,有粉丝在头条里要求分享一下下载地址。一、各平台下载地址1.1 Linux x...

Oracel:ORA-12518:监听程序无法分发客户机连接

一、【问题描述】 最近,在系统高峰期的时候,会提示如上的错误,致使无法连接到服务器上的数据库。二、【分析过程】 1、首先判断是否由于监听配置不正确的原因导致? 系统在正常情况下都可以正常的使用,检查监...