Linux下线程同步的方法

news/2025/1/16 2:35:26/

在Linux下,线程同步是保证多个线程在共享资源时,不会发生数据冲突或资源不一致的关键技术。以下是Linux下常用的几种线程同步方法,以及每种方法的简要解释和示例代码。

1. 互斥锁 (Mutex)

互斥锁是一种最基本的同步机制,它确保在任意时刻,只有一个线程可以访问共享资源。

示例代码:

#include <pthread.h>
#include <stdio.h>pthread_mutex_t lock;  // 定义互斥锁
int shared_resource = 0;void* increment(void* arg) {pthread_mutex_lock(&lock);  // 加锁shared_resource++;printf("Shared Resource: %d\n", shared_resource);pthread_mutex_unlock(&lock);  // 解锁return NULL;
}int main() {pthread_t t1, t2;pthread_mutex_init(&lock, NULL);  // 初始化互斥锁pthread_create(&t1, NULL, increment, NULL);pthread_create(&t2, NULL, increment, NULL);pthread_join(t1, NULL);pthread_join(t2, NULL);pthread_mutex_destroy(&lock);  // 销毁互斥锁return 0;
}

2. 读写锁 (Read-Write Lock)

读写锁允许多个线程同时读取共享资源,但在写入时,其他线程不能读取或写入。

示例代码:

#include <pthread.h>
#include <stdio.h>pthread_rwlock_t rwlock;
int shared_resource = 0;void* reader(void* arg) {pthread_rwlock_rdlock(&rwlock);  // 加读锁printf("Reader: %d\n", shared_resource);pthread_rwlock_unlock(&rwlock);  // 解锁return NULL;
}void* writer(void* arg) {pthread_rwlock_wrlock(&rwlock);  // 加写锁shared_resource++;printf("Writer: %d\n", shared_resource);pthread_rwlock_unlock(&rwlock);  // 解锁return NULL;
}int main() {pthread_t t1, t2;pthread_rwlock_init(&rwlock, NULL);  // 初始化读写锁pthread_create(&t1, NULL, reader, NULL);pthread_create(&t2, NULL, writer, NULL);pthread_join(t1, NULL);pthread_join(t2, NULL);pthread_rwlock_destroy(&rwlock);  // 销毁读写锁return 0;
}

3. 信号量 (Semaphore)

信号量是一种用于控制多个线程对共享资源访问的计数器,特别适用于控制一定数量的资源。

示例代码:

#include <pthread.h>
#include <semaphore.h>
#include <stdio.h>sem_t semaphore;
int shared_resource = 0;void* worker(void* arg) {sem_wait(&semaphore);  // 等待信号量shared_resource++;printf("Shared Resource: %d\n", shared_resource);sem_post(&semaphore);  // 释放信号量return NULL;
}int main() {pthread_t t1, t2;sem_init(&semaphore, 0, 1);  // 初始化信号量,初始值为1pthread_create(&t1, NULL, worker, NULL);pthread_create(&t2, NULL, worker, NULL);pthread_join(t1, NULL);pthread_join(t2, NULL);sem_destroy(&semaphore);  // 销毁信号量return 0;
}

4. 条件变量 (Condition Variable)

条件变量让线程在满足某个条件时等待或唤醒其他线程,常与互斥锁结合使用。

示例代码:

#include <pthread.h>
#include <stdio.h>pthread_mutex_t lock;
pthread_cond_t cond;
int ready = 0;void* wait_for_signal(void* arg) {pthread_mutex_lock(&lock);while (!ready) {pthread_cond_wait(&cond, &lock);  // 等待条件变量}printf("Signal received!\n");pthread_mutex_unlock(&lock);return NULL;
}void* send_signal(void* arg) {pthread_mutex_lock(&lock);ready = 1;pthread_cond_signal(&cond);  // 发送信号pthread_mutex_unlock(&lock);return NULL;
}int main() {pthread_t t1, t2;pthread_mutex_init(&lock, NULL);pthread_cond_init(&cond, NULL);pthread_create(&t1, NULL, wait_for_signal, NULL);pthread_create(&t2, NULL, send_signal, NULL);pthread_join(t1, NULL);pthread_join(t2, NULL);pthread_mutex_destroy(&lock);pthread_cond_destroy(&cond);return 0;
}

以上是几种常见的Linux线程同步方法,每种方法都有其适用的场景。选择合适的同步机制,能够有效防止竞争条件,保证多线程程序的正确性和稳定性。

5. 屏障(Barrier)

屏障用于阻止一组线程中的任何一个继续执行,直到所有线程都到达屏障点。

  • 使用场景:当多个线程需要在某个点进行同步,并确保所有线程都到达某个状态后再继续执行时。
  • 示例
#include <pthread.h>pthread_barrier_t barrier;void* thread_function(void* arg) {// 到达屏障点pthread_barrier_wait(&barrier);// 所有线程都到达屏障点后继续执行return nullptr;
}int main() {pthread_barrier_init(&barrier, NULL, 5);  // 5 表示需要同步的线程数// 创建线程并使用屏障同步pthread_barrier_destroy(&barrier);return 0;
}

6. 自旋锁(Spinlock)

自旋锁是一种忙等待锁,当一个线程尝试获取锁时,如果锁已经被其他线程占用,它会一直循环检查锁的状态,而不是进入休眠状态。

  • 使用场景:在锁的持有时间非常短的情况下,使用自旋锁可以避免线程调度的开销。
  • 示例
#include <pthread.h>pthread_spinlock_t spinlock;void* thread_function(void* arg) {pthread_spin_lock(&spinlock);// 临界区代码pthread_spin_unlock(&spinlock);return nullptr;
}int main() {pthread_spin_init(&spinlock, PTHREAD_PROCESS_PRIVATE);// 创建线程并使用自旋锁同步pthread_spin_destroy(&spinlock);return 0;
}

7. 文件锁(File Locking)

文件锁用于多个进程或线程间同步访问文件。flockfcntl 是两种常用的文件锁定方法。

  • 使用场景:多个线程或进程需要同步访问文件资源时。
  • 示例(使用 flock):
#include <sys/file.h>
#include <unistd.h>
#include <fcntl.h>void lock_file(int fd) {flock(fd, LOCK_EX);  // 独占锁// 文件操作flock(fd, LOCK_UN);  // 解锁
}int main() {int fd = open("file.txt", O_RDWR);lock_file(fd);close(fd);return 0;
}

http://www.ppmy.cn/news/1520263.html

相关文章

无需前端技能:如何使用 Amis 框架简化页面开发

Amis 是一个由百度开源的前端低代码框架&#xff0c;它允许开发者通过 JSON 配置文件来快速生成各种后台管理页面。Amis 的设计理念是通过配置而非编码来实现页面的构建&#xff0c;这使得即使是不熟悉前端技术的开发者也能快速上手。Amis 提供了丰富的组件库和模板&#xff0c…

Broker服务器模块

一.Broker模块介绍 二.Broker模块具体实现 1. 类的成员变量与构造函数 成员变量 事件循环和TCP服务器: muduo::net::EventLoop _baseloop;muduo::net::TcpServer _server; 这些是muduo库提供的核心组件&#xff0c;负责处理网络事件和管理TCP连接。 消息分发和编码: muduo::…

OceanBase 关于 place_group_by HINT的使用

PLACE_GROUP_BY Hint 表示在多表关联时&#xff0c;如果满足单表查询后直接进行group by 的情形下&#xff0c;在跟其它表进行关联统计&#xff0c;减少表内部联接。 NO_PLACE_GROUP_BY Hint 表示在多表关联时&#xff0c;在关联后才对结果进行group by。 使用place_group_by …

系统编程-数据库

数据库 目录 数据库 引入 1、先安装数据库 2、数据库设置密码 3、数据库的进入和退出(前提 你的密码更改过了) 数据库的基本操作 1、显示所有的数据库 2、创建数据库 3、删除数据库 4、选择数据库 在数据库中对表进行操作 1、查看当前数据库中的表 2、在数据库中…

ET6框架(七)Excel配置工具

文章目录 一、Excel表的基本规则&#xff1a;二、特殊特殊标记三、编译路径说明四、动态获取数据五、可导表类型查看: 一、Excel表的基本规则&#xff1a; 在框架中我们的Excel配置表在ET > Excel文件夹中 1.在表结构中需要注意的是起始点必须在第三行第三列&#xff0c;且…

Leetcode面试经典150题-123.买卖股票的最佳时机III

解法都在代码里&#xff0c;不懂就留言或者私信 建议看这个之前先看股票系列的其他问题123.买卖股票的最佳时机III Leetcode面试经典150题-121.买卖股票的最佳时机-CSDN博客 Leetcode面试经典150题-122.买卖股票的最佳时机II-CSDN博客 Leetcode面试经典150题-188.买卖股票的…

Android Framework(三)Activity启动流程

文章目录 大纲总体流程 第一阶段&#xff1a;点击图标启动应用流程概览SourceActivity端处理system_service处理启动请求参数的构建activityInfo的解析创建ActivityRecord 窗口层级树的处理获取Task--getOrCreateRootTaskActivityRecord挂载到Task--setNewTask移动Task到容器顶…

MySQL集群技术4——MySQL路由

mysql-route MySQL 路由&#xff08;Routing&#xff09;通常指的是在 MySQL 架构中如何处理客户端请求和数据流向的问题。在 MySQL 中&#xff0c;路由可以涉及多种不同的场景和技术&#xff0c;包括但不限于反向代理、负载均衡、读写分离等。下面我将详细介绍这些场景和技术…