Linux和windows进程同步与线程同步那些事儿(三): Linux线程同步详解示例

2024-01-10 16:04

本文主要是介绍Linux和windows进程同步与线程同步那些事儿(三): Linux线程同步详解示例,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Linux和windows进程同步与线程同步那些事儿(一)
Linux和windows进程同步与线程同步那些事儿(二): windows线程同步详解示例
Linux和windows进程同步与线程同步那些事儿(三): Linux线程同步详解示例
Linux和windows进程同步与线程同步那些事儿(四):windows 下进程同步
Linux和windows进程同步与线程同步那些事儿(五):Linux下进程同步

在Linux中,线程同步可以通过多种机制来实现,其中最常见的包括互斥锁(mutex)、条件变量(condition variable)和信号量(semaphore)。

1. 互斥锁(Mutex):

互斥锁是最常用的线程同步机制,它可以确保在同一时间只有一个线程可以访问共享资源。
在Linux中,可以使用pthread_mutex_t类型的互斥锁来实现线程同步。

代码示例:

#include <stdio.h>
#include <pthread.h>int global_variable = 0;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;void* thread_function(void* arg) {for (int i = 0; i < 1000; i++) {// 加锁pthread_mutex_lock(&mutex);// 修改全局变量global_variable++;// 解锁pthread_mutex_unlock(&mutex);}return NULL;
}int main() {pthread_t thread1, thread2;// 初始化mutexpthread_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);// 销毁mutexpthread_mutex_destroy(&mutex);printf("Global variable value: %d\n", global_variable);return 0;
}

2. 条件变量(Condition Variable):

条件变量用于线程间的通信和同步,允许线程等待某个特定条件的发生。
在Linux中,可以使用pthread_cond_t类型的条件变量来实现线程同步。

条件变量是一种同步机制,它允许线程在满足特定条件之前等待,并在条件满足时被其他线程通知。

示例代码:演示如何使用条件变量来控制多线程修改全局变量的值:

#include <stdio.h>
#include <pthread.h>int global_var = 0;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;void* thread_function(void* arg)
{int new_value = *(int*)arg;pthread_mutex_lock(&mutex);// 等待条件满足while (global_var != 0){pthread_cond_wait(&cond, &mutex);}// 修改全局变量的值global_var = new_value;printf("Thread %d has modified global_var to %d\n", pthread_self(), global_var);// 通知其他线程条件已经满足pthread_cond_broadcast(&cond);pthread_mutex_unlock(&mutex);return NULL;
}int main()
{pthread_t thread1, thread2;int value1 = 123, value2 = 456;// 创建两个线程pthread_create(&thread1, NULL, thread_function, &value1);pthread_create(&thread2, NULL, thread_function, &value2);pthread_join(thread1, NULL);pthread_join(thread2, NULL);printf("Final value of global_var is %d\n", global_var);return 0;
}

在上面的代码中,有两个线程分别调用thread_function函数。此函数接收一个整数参数作为新的全局变量值。线程首先获得互斥锁并进入临界区,然后使用pthread_cond_wait函数等待条件满足。只有当全局变量global_var的值为0时,线程才被允许修改这个变量的值。一旦满足这个条件,线程就会修改全局变量的值,并通过pthread_cond_broadcast函数通知其他等待这个条件的线程。最后,线程释放互斥锁并退出。

main函数中,我们创建了两个线程并等待它们完成。然后,我们打印最终的全局变量值。

通过使用条件变量,我们可以确保全局变量只能在满足特定条件时被修改,从而避免竞态条件和数据竞争的问题。

请注意,上述代码只是一个示例,用于说明如何使用条件变量来控制多线程修改全局变量的值。在实际的应用中,您可能还需要考虑其他方面,如错误处理和性能优化等。

3. 信号量(Semaphore):

信号量是一种经典的线程同步机制,它可以用于控制对共享资源的访问。
在Linux中,可以使用sem_t类型的信号量来实现线程同步。

在Linux下,我们可以使用信号量来实现对多线程修改全局变量的值的控制。信号量是一种用于进程间同步和互斥的机制,可以用来控制对共享资源的访问。

信号量可以分为二进制信号量计数信号量。二进制信号量只能取0或1,用于互斥操作。计数信号量可以取多个非负整数值,用于同步操作。

下面是一个简单的示例代码,实现了两个线程对全局变量进行自增操作的互斥控制:

#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>int global_var = 0;
sem_t sem;void* thread_func(void* arg) {int i;for (i = 0; i < 100000; i++) {sem_wait(&sem); // 等待信号量,若为0则阻塞global_var++;sem_post(&sem); // 释放信号量,唤醒等待的线程}return NULL;
}int main() {pthread_t thread1, thread2;sem_init(&sem, 0, 1); // 初始化信号量,初始值为1pthread_create(&thread1, NULL, thread_func, NULL);pthread_create(&thread2, NULL, thread_func, NULL);pthread_join(thread1, NULL);pthread_join(thread2, NULL);sem_destroy(&sem); // 销毁信号量printf("Global variable value: %d\n", global_var);return 0;
}

在上面的示例中,我们首先通过 sem_init 函数初始化了一个计数信号量 sem,初始值为1。然后创建了两个线程,并通过 pthread_create 函数将其与 thread_func 函数绑定。thread_func 函数中通过 sem_wait 函数等待信号量,当信号量的值为0时则阻塞,否则减1并继续执行。在对全局变量进行自增操作后,通过 sem_post 函数释放信号量,唤醒等待的线程。最后,通过 sem_destroy 函数销毁信号量。

运行该程序,两个线程会对全局变量 global_var 进行自增操作,由于信号量的存在,每次只能有一个线程能够修改该变量,从而实现了对全局变量访问的互斥控制。最终输出的全局变量值应为 200000。

需要注意的是,信号量的使用需要谨慎,错误的使用可能导致死锁等问题。确保在必要的时候对信号量加锁和解锁,并根据实际需求选择合适的信号量类型。


这些线程同步机制都可以通过Linux提供的pthread库来使用。在实际编程中,选择合适的线程同步机制取决于具体的应用场景和需求,以确保线程间的安全访问和协调。


拓展:
在 Linux 中编译依赖 pthread 库的程序,可以使用以下命令行表达式来编译:

gcc -o output_file source_file.c -lpthread

其中,output_file 是编译后生成的可执行文件的文件名,source_file.c 是需要编译的源代码文件的文件名。

选项 -lpthread 表示链接 pthread 库,将其加入到编译过程中。

如果源文件有多个,可以将它们一一列出来,例如:

gcc -o output_file source_file1.c source_file2.c -lpthread

这篇关于Linux和windows进程同步与线程同步那些事儿(三): Linux线程同步详解示例的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/591336

相关文章

Java利用@SneakyThrows注解提升异常处理效率详解

《Java利用@SneakyThrows注解提升异常处理效率详解》这篇文章将深度剖析@SneakyThrows的原理,用法,适用场景以及隐藏的陷阱,看看它如何让Java异常处理效率飙升50%,感兴趣的... 目录前言一、检查型异常的“诅咒”:为什么Java开发者讨厌它1.1 检查型异常的痛点1.2 为什么说

Linux实现查看某一端口是否开放

《Linux实现查看某一端口是否开放》文章介绍了三种检查端口6379是否开放的方法:通过lsof查看进程占用,用netstat区分TCP/UDP监听状态,以及用telnet测试远程连接可达性... 目录1、使用lsof 命令来查看端口是否开放2、使用netstat 命令来查看端口是否开放3、使用telnet

MySQL的配置文件详解及实例代码

《MySQL的配置文件详解及实例代码》MySQL的配置文件是服务器运行的重要组成部分,用于设置服务器操作的各种参数,下面:本文主要介绍MySQL配置文件的相关资料,文中通过代码介绍的非常详细,需要... 目录前言一、配置文件结构1.[mysqld]2.[client]3.[mysql]4.[mysqldum

Linux系统管理与进程任务管理方式

《Linux系统管理与进程任务管理方式》本文系统讲解Linux管理核心技能,涵盖引导流程、服务控制(Systemd与GRUB2)、进程管理(前台/后台运行、工具使用)、计划任务(at/cron)及常用... 目录引言一、linux系统引导过程与服务控制1.1 系统引导的五个关键阶段1.2 GRUB2的进化优

springboot2.1.3 hystrix集成及hystrix-dashboard监控详解

《springboot2.1.3hystrix集成及hystrix-dashboard监控详解》Hystrix是Netflix开源的微服务容错工具,通过线程池隔离和熔断机制防止服务崩溃,支持降级、监... 目录Hystrix是Netflix开源技术www.chinasem.cn栈中的又一员猛将Hystrix熔

Java调用Python脚本实现HelloWorld的示例详解

《Java调用Python脚本实现HelloWorld的示例详解》作为程序员,我们经常会遇到需要在Java项目中调用Python脚本的场景,下面我们来看看如何从基础到进阶,一步步实现Java与Pyth... 目录一、环境准备二、基础调用:使用 Runtime.exec()2.1 实现步骤2.2 代码解析三、

python之uv使用详解

《python之uv使用详解》文章介绍uv在Ubuntu上用于Python项目管理,涵盖安装、初始化、依赖管理、运行调试及Docker应用,强调CI中使用--locked确保依赖一致性... 目录安装与更新standalonepip 安装创建php以及初始化项目依赖管理uv run直接在命令行运行pytho

Python中yield的用法和实际应用示例

《Python中yield的用法和实际应用示例》在Python中,yield关键字主要用于生成器函数(generatorfunctions)中,其目的是使函数能够像迭代器一样工作,即可以被遍历,但不会... 目录python中yield的用法详解一、引言二、yield的基本用法1、yield与生成器2、yi

Springboot项目构建时各种依赖详细介绍与依赖关系说明详解

《Springboot项目构建时各种依赖详细介绍与依赖关系说明详解》SpringBoot通过spring-boot-dependencies统一依赖版本管理,spring-boot-starter-w... 目录一、spring-boot-dependencies1.简介2. 内容概览3.核心内容结构4.

MySQL中REPLACE函数与语句举例详解

《MySQL中REPLACE函数与语句举例详解》在MySQL中REPLACE函数是一个用于处理字符串的强大工具,它的主要功能是替换字符串中的某些子字符串,:本文主要介绍MySQL中REPLACE函... 目录一、REPLACE()函数语法:参数说明:功能说明:示例:二、REPLACE INTO语句语法:参数