当前位置: 首页 > wzjs >正文

前端开发培训要多少钱seo推广服务哪家好

前端开发培训要多少钱,seo推广服务哪家好,机电建设工程施工网站,生活中花钱请人做网站一、多线程对共享变量的非互斥访问 我们将要做的&#xff1a;构造多线程共享变量竞争的案例&#xff0c;并分析现象发生的原因&#xff0c;进而思考解决方式。 案例源代码&#xff1a; #include <stdio.h> #include <stdlib.h> #include <pthread.h> #inc…

一、多线程对共享变量的非互斥访问

我们将要做的:构造多线程共享变量竞争的案例,并分析现象发生的原因,进而思考解决方式。

案例源代码:

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#include <string.h>int num=30,count=10;void *sub1(void *arg) {int i = 0,tmp;for (; i <count; i++){tmp=num-1;usleep(13);num=tmp;printf("线程1 num减1后值为: %d\n",num);}return ((void *)0);
}
void *sub2(void *arg){int i=0,tmp;for(;i<count;i++){tmp=num-1;usleep(31);num=tmp;printf("线程2 num减1后值为: %d\n",num);}return ((void *)0);
}
int main(int argc, char** argv) {pthread_t tid1,tid2; // 两个子线程的idint err,i=0,tmp;void *tret; // 线程返回值err=pthread_create(&tid1,NULL,sub1,NULL);if(err!=0){printf("pthread_create error:%s\n",strerror(err));exit(-1);}err=pthread_create(&tid2,NULL,sub2,NULL);if(err!=0){printf("pthread_create error:%s\n",strerror(err));exit(-1);}for(;i<count;i++){tmp=num-1;usleep(5);num=tmp;printf("main num减1后值为: %d\n",num);}printf("两个线程运行结束\n");err=pthread_join(tid1,&tret);if(err!=0){printf("can not join with thread1:%s\n",strerror(err));exit(-1);}printf("thread 1 exit code %d\n",(int)tret);err=pthread_join(tid2,&tret);if(err!=0){printf("can not join with thread1:%s\n",strerror(err));exit(-1);}printf("thread 2 exit code %d\n",(int)tret);return 0;
}

🧠 1. 程序功能概述

创建了两个线程 sub1sub2,以及主线程三者共同对一个全局变量 num 执行减 1 操作,共减去 count * 3 = 30 次。

初始值:

int num = 30, count = 10;

所以理论上最终 num == 0,但实际上并不一定!


⚠️ 2. 存在的核心问题:数据竞争(Race Condition)

❗ 对 num-- 是分三步执行的:
tmp = num - 1;
usleep(x);
num = tmp;

这个过程不是原子操作,多个线程可能“交叉”访问这个变量,造成竞态条件(Race Condition)

中间插入 usleep() 只是为了放大并发写入带来的冲突概率,模拟真实环境下的并发问题。

举例说明:

假设此时 num = 10,两个线程同时读到:

线程1:tmp1 = 10 - 1 = 9,睡眠
线程2:tmp2 = 10 - 1 = 9,睡眠

然后:

线程1醒来执行 num = 9
线程2醒来执行 num = 9 (覆盖了线程1的操作)

🔴 这样 num 实际只减少了一次,而我们期望它减少两次(一个线程分别减少一次)!


🔍 3. 运行效果举例(输出可能类似):

线程1 num减1后值为: 29
线程2 num减1后值为: 28
main num减1后值为: 27
线程1 num减1后值为: 27  ←❗ 重复了
main num减1后值为: 26
线程2 num减1后值为: 26  ←❗ 再次重复

最终 num 的值可能 不是 0,甚至是更高。原因就是上面说的:很多次减法操作失效了。


✅4. 如何解决?使用线程同步机制:互斥锁 pthread_mutex_t

例如,添加全局互斥锁

pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;

将每个对 num 的访问部分用锁保护:

pthread_mutex_lock(&lock);
tmp = num - 1;
usleep(13); // 保留你原来的模拟处理
num = tmp;
pthread_mutex_unlock(&lock);

🔒 这样确保每次只有一个线程在访问和修改 num


🛠️ 5. 修改后关键片段示例(以 sub1 为例)

void *sub1(void *arg) {int i = 0, tmp;for (; i < count; i++) {pthread_mutex_lock(&lock);tmp = num - 1;usleep(13);num = tmp;printf("线程1 num减1后值为: %d\n", num);pthread_mutex_unlock(&lock);}return ((void *)0);
}

主线程、sub2 中也要加锁。


🔚 6. 总结

问题说明
数据竞争多线程访问全局变量未加锁
后果num 最终值不确定,减法丢失
解决使用 pthread_mutex 互斥锁
调试建议加 -fsanitize=thread 或使用 valgrind --tool=helgrind 检查

二、并发线程同步与互斥

本次案例是在前一个案例「多线程对共享变量的非互斥访问」的基础上进行了修复和优化,引入了 pthread_mutex 互斥锁机制,实现了 多线程对共享变量的互斥访问控制,有效解决了数据竞争问题。

案例源代码:

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#include <string.h>
int num=30, count=10;
pthread_mutex_t mylock=PTHREAD_MUTEX_INITIALIZER;
void *sub1(void *arg) {int i = 0,tmp;for (; i<count; i++){pthread_mutex_lock(&mylock);   // 上锁		tmp=num-1;usleep(13);num=tmp;pthread_mutex_unlock(&mylock); // 解锁	printf("线程1  第「%d」次num减1后值为: %d\n",i+1,num);}return ((void *)0);
}
void *sub2(void *arg){int i=0,tmp;for(;i<count;i++){pthread_mutex_lock(&mylock); // 上锁tmp=num-1;usleep(31);num=tmp;pthread_mutex_unlock(&mylock); // 解锁printf("线程2  第「%d」次num减1后值为: %d\n",i+1,num);}return ((void *)0);
}
int main(int argc, char** argv) {pthread_t tid1,tid2;int err,i=0,tmp;void *tret; // 线程返回值err=pthread_create(&tid1,NULL,sub1,NULL);if(err!=0){printf("pthread_create error:%s\n",strerror(err));exit(-1);}err=pthread_create(&tid2,NULL,sub2,NULL);if(err!=0){printf("pthread_create error:%s\n",strerror(err));exit(-1);}for(;i<count;i++){pthread_mutex_lock(&mylock); // 主线程上锁tmp=num-1;usleep(5); // num=tmp;		pthread_mutex_unlock(&mylock); // 主线程释放锁printf("主线程 第「%d」次num减1后值为: %d\n",i+1,num);}printf("两个线程运行结束\n");err=pthread_join(tid1,&tret);if(err!=0){printf("can not join with thread1:%s\n",strerror(err));exit(-1);}printf("thread 1 exit code %d\n",(int)tret);err=pthread_join(tid2,&tret);if(err!=0){printf("can not join with thread1:%s\n",strerror(err));exit(-1);}printf("thread 2 exit code %d\n",(int)tret);return 0;
}

下面从结构和功能两个维度逐段讲解这段代码。


✅ 1. 程序功能概述

多线程同时对一个共享变量 num 进行减 1 操作,为避免多个线程同时访问导致的数据错误,使用 互斥锁 pthread_mutex_t 实现同步,确保线程间的安全访问。


🔧 2. 头文件说明

#include <stdio.h>      // printf()
#include <stdlib.h>     // exit()
#include <pthread.h>    // pthread_create, pthread_join, pthread_mutex_*
#include <unistd.h>     // usleep()
#include <string.h>     // strerror()

✅ 上述头文件提供了线程创建、同步、休眠和错误信息处理等功能。


🔐 3. 全局变量及互斥锁

int num=30, count=10;
pthread_mutex_t mylock = PTHREAD_MUTEX_INITIALIZER;
  • num: 被所有线程共享的变量,初始为 30。
  • count: 每个线程循环次数。
  • mylock: 全局互斥锁,用于防止多个线程同时修改 num

🧵 4. 线程函数 sub1 和 sub2

🔹 sub1 函数
void *sub1(void *arg) {int i = 0, tmp;for (; i < count; i++) {pthread_mutex_lock(&mylock);      // 上锁tmp = num - 1;usleep(13);                       // 模拟计算耗时num = tmp;pthread_mutex_unlock(&mylock);    // 解锁printf("线程1 第【%d】num减1后值为: %d\n", i, num);}return ((void *)0);
}
🔹 sub2 函数
void *sub2(void *arg) {int i = 0, tmp;for (; i < count; i++) {pthread_mutex_lock(&mylock);tmp = num - 1;usleep(31);num = tmp;pthread_mutex_unlock(&mylock);printf("线程2 第【%d】num减1后值为: %d\n", i, num);}return ((void *)0);
}

🟡 共同点:

  • 都对共享变量 num 执行减 1 操作。
  • 每次操作前后都加了互斥锁,保证了对 num 的访问是互斥的。

🟡 不同点:

  • 睡眠时间不同,用于模拟线程调度差异,放大并发现象。

👑 5. 主线程 main 函数

1️⃣ 创建线程
pthread_create(&tid1, NULL, sub1, NULL);
pthread_create(&tid2, NULL, sub2, NULL);
  • 启动两个子线程 sub1sub2,它们会与主线程并发执行。

2️⃣ 主线程也参与对 num 的操作
for (; i < count; i++) {pthread_mutex_lock(&mylock);tmp = num - 1;usleep(5);num = tmp;pthread_mutex_unlock(&mylock);printf("main 第【%d】num减1后值为: %d\n", i, num);
}

💡 主线程和子线程一样,每次操作都加锁保护,保证不会同时操作 num,从而避免数据冲突


3️⃣ 等待线程结束并获取退出状态
pthread_join(tid1, &tret);
pthread_join(tid2, &tret);
  • 使用 pthread_join() 等待线程结束。
  • 线程的返回值是 NULL(即 return ((void*)0)),打印时结果是 0

🧪 6. 运行效果示例(输出节选)

主线程 第「1」次num减1后值为: 29
主线程 第「2」次num减1后值为: 28
主线程 第「3」次num减1后值为: 27
线程1  第「1」次num减1后值为: 26
线程1  第「2」次num减1后值为: 25
...

最终:

两个线程运行结束
thread 1 exit code 0
thread 2 exit code 0

🔒 7. 为什么这次没有竞态条件?

因为你加入了 pthread_mutex_lock()pthread_mutex_unlock() 对每一次对 num 的读-改-写操作进行了加锁保护,确保每次修改都是互斥的、完整的


📌 八、总结

项目说明
多线程创建使用 pthread_create 创建两个线程
共享资源所有线程和主线程共享变量 num
数据保护使用 pthread_mutex 实现访问同步,防止竞态
同步结束使用 pthread_join 等待子线程结束
延时模拟使用 usleep() 模拟并发中的调度差异
http://www.dtcms.com/wzjs/216545.html

相关文章:

  • 网站技术架构图产品推广策略
  • 提供完善政府网站建设百度推广创意范例
  • wordpress 一键建站网站建设黄页
  • 做玻璃的网站营销策略范文
  • 网络电话聊天网站建设多少钱桂林网站优化
  • 怎样做汽车网站建设软文发稿公司
  • 亳州建设网站一个网站如何推广
  • 整个网站全部乱码沈阳黄页88企业名录
  • 学生怎么制作网站指数运算法则
  • 哈尔滨网站建设供应商营销企业
  • 个性化定制客户和网站建设roseonly企业网站优化
  • 丽水网站建设seo广告多的网站
  • 淘宝联盟个人网站怎么做网络营销的方式都有哪些
  • wordpress 女性主题成都seo网络优化公司
  • 网站建设丿金手指排名9搜索引擎营销优缺点
  • 设计师互动网站模板建站平台
  • 小企业官方网站制作搜索引擎优化排名培训
  • 网站建设开发案例长沙网站提升排名
  • wordpress 更改自带域名北京优化seo公司
  • 潍坊智能建站模板百度seo关键词优化工具
  • 平面设计教程网站上海做网站优化
  • 网站建设 部署与发布视频教程百度投票人气排行榜入口
  • 自己做网站 有名seo与网络推广的区别和联系
  • 网络网站建设价格啥是网络推广
  • qq企业邮箱登录广州seo公司推荐
  • 古典 网站模板门户网站
  • 西安php网站建设专家市场营销计划方案
  • 做网站开发背景上海怎么做seo推广
  • 登封网站制作网站建设武汉seo培训
  • 自己做的网站首页变成符号了aso优化{ }贴吧