创建线程 ---- 实例

1、C语言 创建线程 执行2个不同的函数:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>// 第一个线程要执行的函数
void* function1(void* arg) {printf("Function 1 is running\n");// 执行一些任务...return NULL;
}// 第二个线程要执行的函数
void* function2(void* arg) {printf("Function 2 is running\n");// 执行一些任务...return NULL;
}int main() {pthread_t thread1, thread2;// 创建第一个线程执行function1if (pthread_create(&thread1, NULL, function1, NULL) != 0) {perror("Failed to create thread 1");return EXIT_FAILURE;}// 创建第二个线程执行function2if (pthread_create(&thread2, NULL, function2, NULL) != 0) {perror("Failed to create thread 2");return EXIT_FAILURE;}// 等待第一个线程结束if (pthread_join(thread1, NULL) != 0) {perror("Failed to join thread 1");return EXIT_FAILURE;}// 等待第二个线程结束if (pthread_join(thread2, NULL) != 0) {perror("Failed to join thread 2");return EXIT_FAILURE;}printf("Both threads have finished\n");return EXIT_SUCCESS;
}

2、C 创建两个线程 通过传递数组 执行同一个函数 打印数组的内容:

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>// 线程要执行的函数,接受一个void*类型的参数,这里参数是一个指向整型数组的指针
void* print_array(void* arg) {int* array = (int*)arg;int size = 5;printf("Array contents: ");for (int i = 0; i < size; ++i) {printf("%d ", array[i]);}printf("\n");return NULL;
}int main() {pthread_t thread1, thread2;int array1[] = {1, 2, 3, 4, 5};int array2[] = {6, 7, 8, 9, 10};// 创建第一个线程,传递array1作为参数if (pthread_create(&thread1, NULL, print_array, (void*)array1) != 0) {perror("Failed to create thread 1");return EXIT_FAILURE;}// 创建第二个线程,传递array2作为参数if (pthread_create(&thread2, NULL, print_array, (void*)array2) != 0) {perror("Failed to create thread 2");return EXIT_FAILURE;}// 等待第一个线程结束if (pthread_join(thread1, NULL) != 0) {perror("Failed to join thread 1");return EXIT_FAILURE;}// 等待第二个线程结束if (pthread_join(thread2, NULL) != 0) {perror("Failed to join thread 2");return EXIT_FAILURE;}printf("Both threads have finished\n");return EXIT_SUCCESS;
}

3、C 创建两个线程 访问一个全局变量:

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>// 全局变量
int global_variable = 0;// 互斥锁
pthread_mutex_t lock;// 线程要执行的函数
void* increment(void* arg) {// 锁定互斥锁pthread_mutex_lock(&lock);// 访问和修改全局变量:实际上是对锁进行操作,把内容放在 锁->内容ops->解锁 中// 这里可以加上 内核那本书里面的设计与实现 什么时候需要加锁!global_variable++;printf("Global variable incremented to: %d\n", global_variable);// 解锁互斥锁pthread_mutex_unlock(&lock);return NULL;
}int main() {pthread_t thread1, thread2;// 初始化互斥锁if (pthread_mutex_init(&lock, NULL) != 0) {perror("Failed to initialize mutex");return EXIT_FAILURE;}// 创建两个线程if (pthread_create(&thread1, NULL, increment, NULL) != 0) {perror("Failed to create thread 1");return EXIT_FAILURE;}if (pthread_create(&thread2, NULL, increment, NULL) != 0) {perror("Failed to create thread 2");return EXIT_FAILURE;}// 等待两个线程结束pthread_join(thread1, NULL);pthread_join(thread2, NULL);// 销毁互斥锁pthread_mutex_destroy(&lock);printf("Final value of global variable: %d\n", global_variable);return EXIT_SUCCESS;
}

读取-修改竞态条件(Read-Modify-Write Race Condition):当一个线程正在读取变量的值时,另一个线程可能会修改这个变量。如果第一个线程在读取过程中第二个线程改变了变量的值,第一个线程可能会得到一个不一致的值。

内存可见性问题:在某些编译器和处理器优化下,没有锁的保护可能导致一个线程看不到另一个线程对共享变量所做的修改,因为编译器和处理器可能会对内存访问进行重排序。

数据依赖性问题:如果shared_data的值依赖于程序中的其他状态,并且这些状态可能被其他线程修改,那么即使只是读取shared_data,也需要确保在读取时这些依赖状态不会被改变。

为了保证线程安全和数据的一致性,即使是读取操作,也应该在修改和读取共享变量时使用互斥锁。这样可以确保在任何时候只有一个线程能够访问共享变量,无论是读取还是写入。

在实际应用中,如果性能是一个关键考虑因素,并且读操作远远多于写操作,可以考虑使用其他同步机制,如 读写锁(read-write lock),它允许多个线程同时读取,但在写入时仍然保证互斥。 然而,这仍然需要仔细设计以避免潜在的死锁和性能问题。对于简单的用例或者写操作较为频繁的情况,使用互斥锁通常是最直接和安全的方法。

4、C 创建两个线程 读写一个全局变量:

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>// 全局变量
int shared_data = 0;// 互斥锁
pthread_mutex_t mutex;// 读取全局变量的线程函数
void* reader(void* arg) {int data;pthread_mutex_lock(&mutex);data = shared_data;pthread_mutex_unlock(&mutex);printf("Reader thread read data: %d\n", data);return NULL;
}// 修改全局变量的线程函数
void* writer(void* arg) {pthread_mutex_lock(&mutex);shared_data = *(int*)arg;pthread_mutex_unlock(&mutex);printf("Writer thread wrote data: %d\n", shared_data);return NULL;
}int main() {pthread_t reader_thread, writer_thread;int new_data = 42;// 初始化互斥锁if (pthread_mutex_init(&mutex, NULL) != 0) {perror("Failed to initialize mutex");return EXIT_FAILURE;}// 创建读取线程if (pthread_create(&reader_thread, NULL, reader, NULL) != 0) {perror("Failed to create reader thread");return EXIT_FAILURE;}// 创建写入线程if (pthread_create(&writer_thread, NULL, writer, (void*)&new_data) != 0) {perror("Failed to create writer thread");return EXIT_FAILURE;}// 等待线程结束pthread_join(reader_thread, NULL);pthread_join(writer_thread, NULL);// 销毁互斥锁pthread_mutex_destroy(&mutex);return EXIT_SUCCESS;
}

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

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

相关文章

Linux介绍与安装CentOS 7操作系统

什么是操作系统 操作系统&#xff0c;英⽂名称 Operating System&#xff0c;简称 OS&#xff0c;是计算机系统中必不 可少的基础系统软件&#xff0c;它是 应⽤程序运⾏以及⽤户操作必备的基础环境 ⽀撑&#xff0c;是计算机系统的核⼼。 操作系统的作⽤是管理和控制计算机系…

【Linux】深入理解进程信号机制:信号的产生、捕获与阻塞

&#x1f3ac; 个人主页&#xff1a;谁在夜里看海. &#x1f4d6; 个人专栏&#xff1a;《C系列》《Linux系列》《算法系列》 ⛰️ 时间不语&#xff0c;却回答了所有问题 目录 &#x1f4da;前言 &#x1f4da;一、信号的本质 &#x1f4d6;1.异步通信 &#x1f4d6;2.信…

【西门子PLC.博途】——面向对象编程及输入输出映射FC块

当我们做面向对象编程的时候&#xff0c;需要用到输入输出的映射。这样建立的变量就能够被复用&#xff0c;从而最大化利用了我们建立的udt对象。 下面就来讲讲映射是什么。 从本质上来说&#xff0c;映射就是拿实际物理对象对应程序虚拟对象&#xff0c;假设程序对象是I0.0&…

MySQL索引的理解

MySQL与磁盘的交互 根据冯诺依曼结构体系&#xff0c;我们知道我们任何上层的应用想要去访问磁盘就必须要通过内存来访问&#xff0c;MySQL作为一款储存数据的服务&#xff0c;肯定是很多时间要用来访问磁盘。而大量访问磁盘一定会影响运行效率的在innoDB的存储引擎下为了减少…

分布式全文检索引擎ElasticSearch-数据的写入存储底层原理

一、数据写入的核心流程 当向 ES 索引写入数据时&#xff0c;整体流程如下&#xff1a; 1、客户端发送写入请求 客户端向 ES 集群的任意节点&#xff08;称为协调节点&#xff0c;Coordinating Node&#xff09;发送一个写入请求&#xff0c;比如 index&#xff08;插入或更…

Maven 生命周期

文章目录 Maven 生命周期- Clean 生命周期- Build 生命周期- Site 生命周期 Maven 生命周期 Maven 有以下三个标准的生命周期&#xff1a; Clean 生命周期&#xff1a; clean&#xff1a;删除目标目录中的编译输出文件。这通常是在构建之前执行的&#xff0c;以确保项目从一个…

Android Studio AI助手---Gemini

从金丝雀频道下载最新版 Android Studio&#xff0c;以利用所有这些新功能&#xff0c;并继续阅读以了解新增内容。 Gemini 现在可以编写、重构和记录 Android 代码 Gemini 不仅仅是提供指导。它可以编辑您的代码&#xff0c;帮助您快速从原型转向实现&#xff0c;实现常见的…

#渗透测试#漏洞挖掘#红蓝攻防#护网#sql注入介绍04-盲SQL注入(Blind SQL Injection)

免责声明 本教程仅为合法的教学目的而准备&#xff0c;严禁用于任何形式的违法犯罪活动及其他商业行为&#xff0c;在使用本教程前&#xff0c;您应确保该行为符合当地的法律法规&#xff0c;继续阅读即表示您需自行承担所有操作的后果&#xff0c;如有异议&#xff0c;请立即停…

Scala 的迭代器

迭代器定义&#xff1a;迭代器不是一种集合&#xff0c;它是一种用于访问集合的方法。 迭代器需要通过集合对应的迭代器调用迭代器的方法来访问。 支持函数式编程风格&#xff0c;便于链式操作。 创建一个迭代器&#xff0c;相关代码如下&#xff1a; object Test {def mai…

底层理论基础(单片机)

计算机基础 IO逻辑 计算机系统中的高低电平逻辑1和0&#xff0c;数据在计算机中的存储、传输、运算都是以二进制形式进行的。 数据的传输通过总线真正传递的是电信号&#xff0c;高低电平&#xff08;0、1&#xff09;。运算在电路中进行&#xff0c;集成电路中运算。 计算机的…

B站bilibili视频转文字字幕下载方法

本文将讲述介绍一种使用本地工具如何快速的下载B站的字幕为本地文本文件的方法。 通常获取B站字幕需要在浏览器中安装第三方插件&#xff0c;通过插件获取字幕。随着大模型&#xff0c;生成式AI&#xff0c;ChatGPT的应用&#xff0c;B站也提供了AI小助手对视频的内容进行总结…

ROS+PX4+Gazebo仿真环境配置全流程解析

上一期文章介绍了我们即将发布的仿真平台&#xff0c;并提到后续需要在Ubuntu系统上进行PX4软件在环仿真。本期文章将为大家详细介绍如何配置Ubuntu环境以及安装ROS和PX4仿真环境。具体配置包括&#xff1a;Ubuntu 20.04 ROS Noetic PX4 Python3。 需要注意的是&#xff0c…

基础入门-APP应用微信小程序原生态开发H5+Vue技术WEB封装打包反编译抓包点

知识点&#xff1a; 1、基础入门-APP应用-开发架构安全问题 2、基础入门-小程序应用-开发架构安全问题 通用&#xff1a; 1、反编译-得到源码-源码提取资产&#xff08;泄漏的配置信息&#xff09;-安全测试 2、抓包-资产-安全测试 一、演示案例-移动App-开发架构-原生&H…

Elasticsearch:使用 Open Crawler 和 semantic text 进行语义搜索

作者&#xff1a;来自 Elastic Jeff Vestal 了解如何使用开放爬虫与 semantic text 字段结合来轻松抓取网站并使其可进行语义搜索。 Elastic Open Crawler 演练 我们在这里要做什么&#xff1f; Elastic Open Crawler 是 Elastic 托管爬虫的后继者。 Semantic text 是 Elasti…

Qt之自定义标题栏拓展(十)

Qt开发 系列文章 - user-defined-titlebars&#xff08;十&#xff09; 目录 前言 一、方式一 1.效果演示 2.创建标题栏类 3.可视化UI设计 4.定义相关函数 5.使用标题栏类 二、方式二 1.效果演示 2.创建标题栏类 3.定义相关函数 4.使用标题栏类 总结 前言 Qt自带…

vue3前端组件库的搭建与发布(一)

前言&#xff1a; 最近在做公司项目中&#xff0c;有这么一件事情&#xff0c;很是头疼&#xff0c;就是同一套代码&#xff0c;不同项目&#xff0c;要改相同bug&#xff0c;改好多遍&#xff0c;改的都想吐&#xff0c;于是就想做一个组件库&#xff0c;这样更新一下就全都可…

学技术学英文:代码中的锁:悲观锁和乐观锁

本文导读&#xff1a; 1. 举例说明加锁的场景&#xff1a; 多线程并发情况下有资源竞争的时候&#xff0c;如果不加锁&#xff0c;会出现数据错误&#xff0c;举例说明&#xff1a; 业务需求&#xff1a;账户余额>取款金额&#xff0c;才能取钱。 时间线 两人共有账户 …

Qt编译MySQL数据库驱动

目录 Qt编译MySQL数据库驱动 测试程序 Qt编译MySQL数据库驱动 &#xff08;1&#xff09;先找到MySQL安装路径以及Qt安装路径 C:\Program Files\MySQL\MySQL Server 8.0 D:\qt\5.12.12 &#xff08;2&#xff09;在D:\qt\5.12.12\Src\qtbase\src\plugins\sqldrivers\mysql下…

CTFHUB-web(SSRF)

内网访问 点击进入环境&#xff0c;输入 http://127.0.0.1/flag.php 伪协议读取文件 /?urlfile:///var/www/html/flag.php 右击查看页面源代码 端口扫描 1.根据题目提示我们知道端口号在8000-9000之间,使用bp抓包并进行爆破 POST请求 点击环境&#xff0c;访问flag.php 查看页…

游戏引擎学习第43天

仓库 https://gitee.com/mrxiao_com/2d_game 介绍运动方程 今天我们将更进一步&#xff0c;探索运动方程&#xff0c;了解真实世界中的物理&#xff0c;并调整它们&#xff0c;以创建一种让玩家感觉愉悦的控制体验。这并不是在做一个完美的物理模拟&#xff0c;而是找到最有趣…