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

相关文章

linux生产者,消费者问题

pthread_cond_wait() :用于阻塞当前线程,等待别的线程使用pthread_cond_signal()或pthread_cond_broadcast来唤醒它。 pthread_cond_wait() 必须与pthread_mutex 配套使用。pthread_cond_wait()函数一进入wait状态就会自动release mutex。当其他线程通过pthread

Linux 安装、配置Tomcat 的HTTPS

Linux 安装 、配置Tomcat的HTTPS 安装Tomcat 这里选择的是 tomcat 10.X ,需要Java 11及更高版本 Binary Distributions ->Core->选择 tar.gz包 下载、上传到内网服务器 /opt 目录tar -xzf 解压将解压的根目录改名为 tomat-10 并移动到 /opt 下, 形成个人习惯的路径 /opt/tomcat-10

RedHat运维-Linux文本操作基础-AWK进阶

你不用整理,跟着敲一遍,有个印象,然后把它保存到本地,以后要用再去看,如果有了新东西,你自个再添加。这是我参考牛客上的shell编程专项题,只不过换成了问答的方式而已。不用背,就算是我自己亲自敲,我现在好多也记不住。 1. 输出nowcoder.txt文件第5行的内容 2. 输出nowcoder.txt文件第6行的内容 3. 输出nowcoder.txt文件第7行的内容 4. 输出nowcode

【Linux进阶】UNIX体系结构分解——操作系统,内核,shell

1.什么是操作系统? 从严格意义上说,可将操作系统定义为一种软件,它控制计算机硬件资源,提供程序运行环境。我们通常将这种软件称为内核(kerel),因为它相对较小,而且位于环境的核心。  从广义上说,操作系统包括了内核和一些其他软件,这些软件使得计算机能够发挥作用,并使计算机具有自己的特生。这里所说的其他软件包括系统实用程序(system utility)、应用程序、shell以及公用函数库等

十四、观察者模式与访问者模式详解

21.观察者模式 21.1.课程目标 1、 掌握观察者模式和访问者模式的应用场景。 2、 掌握观察者模式在具体业务场景中的应用。 3、 了解访问者模式的双分派。 4、 观察者模式和访问者模式的优、缺点。 21.2.内容定位 1、 有 Swing开发经验的人群更容易理解观察者模式。 2、 访问者模式被称为最复杂的设计模式。 21.3.观察者模式 观 察 者 模 式 ( Obser

【操作系统】信号Signal超详解|捕捉函数

🔥博客主页: 我要成为C++领域大神🎥系列专栏:【C++核心编程】 【计算机网络】 【Linux编程】 【操作系统】 ❤️感谢大家点赞👍收藏⭐评论✍️ 本博客致力于知识分享,与更多的人进行学习交流 ​ 如何触发信号 信号是Linux下的经典技术,一般操作系统利用信号杀死违规进程,典型进程干预手段,信号除了杀死进程外也可以挂起进程 kill -l 查看系统支持的信号

问题-windows-VPN不正确关闭导致网页打不开

为什么会发生这类事情呢? 主要原因是关机之前vpn没有关掉导致的。 至于为什么没关掉vpn会导致网页打不开,我猜测是因为vpn建立的链接没被更改。 正确关掉vpn的时候,会把ip链接断掉,如果你不正确关掉,ip链接没有断掉,此时你vpn又是没启动的,没有域名解析,所以就打不开网站。 你可以在打不开网页的时候,把vpn打开,你会发现网络又可以登录了。 方法一 注意:方法一虽然方便,但是可能会有

Windows/macOS/Linux 安装 Redis 和 Redis Desktop Manager 可视化工具

本文所有安装都在macOS High Sierra 10.13.4进行,Windows安装相对容易些,Linux安装与macOS类似,文中会做区分讲解 1. Redis安装 1.下载Redis https://redis.io/download 把下载的源码更名为redis-4.0.9-source,我喜欢跟maven、Tomcat放在一起,就放到/Users/zhan/Documents

Jitter Injection详解

一、定义与作用 Jitter Injection,即抖动注入,是一种在通信系统中人为地添加抖动的技术。该技术通过在发送端对数据包进行延迟和抖动调整,以实现对整个通信系统的时延和抖动的控制。其主要作用包括: 改善传输质量:通过调整数据包的时延和抖动,可以有效地降低误码率,提高数据传输的可靠性。均衡网络负载:通过对不同的数据流进行不同程度的抖动注入,可以实现网络资源的合理分配,提高整体传输效率。增

Linux系统稳定性的奥秘:探究其背后的机制与哲学

在计算机操作系统的世界里,Linux以其卓越的稳定性和可靠性著称,成为服务器、嵌入式系统乃至个人电脑用户的首选。那么,是什么造就了Linux如此之高的稳定性呢?本文将深入解析Linux系统稳定性的几个关键因素,揭示其背后的技术哲学与实践。 1. 开源协作的力量Linux是一个开源项目,意味着任何人都可以查看、修改和贡献其源代码。这种开放性吸引了全球成千上万的开发者参与到内核的维护与优化中,形成了