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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/612938.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

CentOS7安装jdk1.8

CentOS7安装jdk1.8 一、解压jdk并放到指定位置二、设置环境变量并生效三、检查是否生效 一、解压jdk并放到指定位置 tar -zxvf jdk-8u25-linux-x64.tar.gz mv jdk-8u25-linux-x64 /home/seven/jdk二、设置环境变量并生效 # 设置环境变量 vim /etc/profile export JAVA_HOME/h…

如何创建自己的小程序?零编程一键创建实战指南

当今瞬息万变的数字世界中&#xff0c;拥有一个属于自己的小程序已成为企业与个人展示、服务和互动的重要途径。无需编码知识&#xff0c;通过便捷的云端可视化平台&#xff0c;也可以轻松创建一款符合自身需求且功能丰富的小程序。下面给大家分享如何创建自己的小程序。 1、选…

消息开始事件message start event

一&#xff1a;bpmn 二&#xff1a;java repositoryService.createDeployment().name("消息事件流程").addClasspathResource("bpmn/msg_event_process.bpmn").deploy(); identityService.setAuthenticatedUserId("huihui"); ProcessInstance p…

js获取光标坐标

方法一: 使用事件对象的clientX和clientY属性获取光标坐标&#xff1a; document.addEventListener(mousemove, function(event) {var x event.clientX;var y event.clientY;console.log(光标位置&#xff1a;, x, y); });方法二: 使用getBoundingClientRect()方法获取目标元…

自适应批量生成二维码源码系统:电脑+手机端自适应 支持任何类型批量生成二维码 附带完整的搭建教程

在当今数字化的时代&#xff0c;二维码已经成为了我们日常生活和工作中的重要组成部分。无论是分享链接、添加好友&#xff0c;还是支付购物&#xff0c;二维码都以其便捷性受到了广泛的欢迎。下面&#xff0c;罗峰就来给大家分享一款自适应批量生成二维码源码系统&#xff0c;…

最新消息:OpenAI GPT Store 正式上线,GPTs 应用商店来了!

原文链接 https://openaigptguide.com/gpt-store-and-chatgpt-team/ OpenAI推出的两款新产品和服务&#xff1a;GPT Store和ChatGPT Team&#xff0c;提供了许多全新的解决方案和功能&#xff0c;旨在帮助用户更轻松地使用和构建GPT工具&#xff0c;同时也增加了公司的收入来源…

Spring Boot 自动装配原理

Java面试题目录 Spring Boot自动装配原理 Spring Boot启动类上的SpringBootApplication注解中包含EnableAutoConfiguration注解&#xff0c;表示开启自动装配。在EnableAutoConfiguration注解中使用Import注解引入AutoConfigurationImportSelector组件&#xff0c;此类中通过S…

【JaveWeb教程】(17) MySQL数据库开发之 MySQL简介、安装、数据类型、SQL通用语法 详细代码示例讲解

目录 前言1. MySQL概述1.1 安装1.1.1 版本1.1.2 安装1.1.3 连接1.1.4 企业使用方式(了解) 1.2 数据模型1.3 SQL简介1.3.1 SQL通用语法1.3.2 分类 前言 在我们讲解SpringBootWeb基础知识(请求响应案例)的时候&#xff0c;我们讲到在web开发中&#xff0c;为了应用程序职责单一&…

Laravel 使用rdkafka_laravel详细教程(实操避坑)

一、选择rdkafka 首先要看版本兼容问题&#xff0c;我的是Laravel5.6&#xff0c;PHP是7.3.13&#xff0c;所以需要下载兼容此的rdkafka&#xff0c;去 Packagist 搜索 kafka &#xff0c;我用的是 Packagist选择里面0.10.5版本&#xff0c; 二、安装rdkafka 在 Laravel 项目…

python爬虫实战(9)--获取澎pai热榜

1. 需要的类包 import pandas as pd import requests2. 请求地址 通过分析&#xff0c;数据可以直接从接口获取&#xff0c;无需解析页面标签&#xff0c;直接取出我们需要的数据即可。 def fetch_hot_news(api_url):response requests.get(api_url)if response.status_cod…

循环打印当前时间的前七个小时

padStart和padEnd是es6中新增的语法 只能对字符串使用&#xff0c;是新增的方法不会修改原字符串 str.padStart(MaxLength,‘填充的内容’) // 当str的长度没有达到MaxLength&#xff0c;会将第二个参数填充到这个str前直到达到MaxLength str.padEnd(MaxLength,‘填充的内容’…

[足式机器人]Part3 机构运动学与动力学分析与建模 Ch00-3(2) 刚体的位形 Configuration of Rigid Body

本文仅供学习使用&#xff0c;总结很多本现有讲述运动学或动力学书籍后的总结&#xff0c;从矢量的角度进行分析&#xff0c;方法比较传统&#xff0c;但更易理解&#xff0c;并且现有的看似抽象方法&#xff0c;两者本质上并无不同。 2024年底本人学位论文发表后方可摘抄 若有…

pyDAL一个python的ORM(9) pyDAL的嵌套查询

假设有以下两个表&#xff1a; db.define_table(person,Field(id, string), Field(‘name, string), Field(‘dept, string)) db.define_table(things,Field(id, string), Field(‘name, string), Field(‘owner, string)) 一、使用belongs进行嵌套查询 我们查询要求&#…

Vue+Element Ui实现el-table自定义表头下拉选择表头筛选

用vueelement ui开发管理系统时&#xff0c;使用el-table做表格&#xff0c;当表格列过多的时候&#xff0c;想要做成可选表头的&#xff0c;实现表格列的筛选显示&#xff0c;效果如下&#xff1a; 代码文件结构&#xff1a; 废话不多说&#xff0c;直接上代码&#xff1a; 第…

2023年,AI爆发的一年

公众号&#xff1a;算法一只狗 今年以来&#xff0c;AI呈爆发式发展。在文本生成的领域&#xff0c;涌现出以ChatGPT为代表的生成式大模型。而在文本图像生成方面&#xff0c;有高度自定义的Stable Diffusion&#xff0c;和简单易用上手的Midjournery。多模态领域更是百花齐放&…

外汇天眼:Options与OneTick合作,共同打造全球SAAS分析平台

Options Technology&#xff0c;一家为全球金融领域提供云服务的托管服务提供商&#xff0c;今天宣布与OneMarketData及其旗舰产品OneTick平台的合作。 Options将使OneTick订户能够访问其庞大的市场数据存储库&#xff0c;包括股票、外汇、期货、期权和固定收益数据&#xff0…

OpenAI GPT商店来了! 创业公司打不过就加入?|对话Agent创业公司S2R

文&#xff5c;郝 鑫 1月10日&#xff0c;OpenAI推出了在线商店“GPT Store”。该商店已于昨日开始向付费用户、团队和企业用户推出&#xff0c;商店汇集了用户为各种任务创建的ChatGPT的自定义版本。 2023年初到年末&#xff0c;Agent就像一位来自异域的吉普赛女郎&#…

JavaScript中要实现爬虫抓取动态滚动条加载的内容Puppeteer

在JavaScript中&#xff0c;要实现爬虫抓取动态滚动条加载的内容&#xff08;即滚动到页面底部时自动加载更多内容的网页&#xff09;&#xff0c;通常需要模拟用户滚动行为&#xff0c;并等待页面内容动态加载完成。由于浏览器环境下的JavaScript并不支持直接用于生产环境的网…

用ChatGPT来造一个ChatGPT:计算机领域智能问答系统实践(1)

随着信息技术的迅猛发展&#xff0c;人们在计算机领域的知识需求日益增长&#xff0c;而传统搜索引擎在回答特定问题时存在一定局限性。一个智能问答系统可以提供更直接、准确的答案&#xff0c;帮助用户更高效地获取所需信息。 此外&#xff0c;计算机领域的知识通常较为复杂…

linux 网络基础配置

将Linux主机接入到网络&#xff0c;需要配置网络相关设置一般包括如下内容&#xff1a; 主机名 iP/netmask (ip地址&#xff0c;网关) 路由&#xff1a;默认网关 网络连接状态 DNS服务器 &#xff08;主DNS服务器 次DNS服务器 第三个DNS服务器&#xff09; 一、…