C语言线程安全问题
线程安全问题
#include <stdio.h>
#include <tinycthread.h>
#include <io_utils.h>
int count = 0;
int Counter(void*arg)
{
for(int i = 0;i<100000;i++)
{
count++;
/*
* int temp = count;
* count=temp+1;
* return temp;
* */
}
return 0;
}
int main()
{
thrd_t t1;
thrd_t t2;
thrd_create(&t1,Counter,NULL);
thrd_create(&t2,Counter,NULL);
thrd_join(t1,NULL);
thrd_join(t2,NULL);
PRINT_INT(count);
return 0;
}
- 运行结果不是所要值原因是count++在并发时产生冲突
线程安全的产生
- 对共享资源进行非原子的访问
- 不同线程之间代码可见性问题
- 线程内部代码编译时的重排序问题
解决方法一 消除副作用
#include <stdio.h>
#include <tinycthread.h>
#include <io_utils.h>
int Counter(void*arg)
{
int count = 0;
for(int i = 0;i<100000;i++)
{
count++;
}
return count;
}
int main()
{
thrd_t t1;
thrd_t t2;
thrd_create(&t1,Counter,NULL);
thrd_create(&t2,Counter,NULL);
int count = 0;
int result = 0;
thrd_join(t1,&result);
count+=result;
thrd_join(t2,&result);
count+=result;
PRINT_INT(count);
return 0;
}
解决方法二 原子类型
#include<stdio.h>
#include <tinycthread.h>
#include <io_utils.h>
#include <stdatomic.h>
atomic_int count = 0; //设置原子类型
int Counter(void*arg)
{
for(int i = 0;i<100000;i++)
{
count++;
}
return 0;
}
int main()
{
thrd_t t1;
thrd_t t2;
thrd_create(&t1,Counter,NULL);
thrd_create(&t2,Counter,NULL);
thrd_join(t1,NULL);
thrd_join(t2,NULL);
PRINT_INT(count);
return 0;
}
解决方法三 原子操作
#include<stdio.h>
#include <tinycthread.h>
#include <io_utils.h>
#include <stdatomic.h>
atomic_flag resume_flag = ATOMIC_FLAG_INIT;
int PrintNumber(void*arg)
{
int current = 0;
while(atomic_flag_test_and_set(&resume_flag))
{
current++;
PRINT_INT(current);
thrd_sleep(&(struct timespec){.tv_sec=1},NULL);
}
return current;
}
int main()
{
atomic_flag_test_and_set(&resume_flag);
thrd_t t;
thrd_create(&t,PrintNumber,NULL);
thrd_sleep(&(struct timespec){.tv_sec=5},NULL);
atomic_flag_clear(&resume_flag);
int last_number = 0;
thrd_join(t,&last_number);
PRINT_INT(last_number);
return 0;
}
解决方法四 锁
#include <stdio.h>
#include <tinycthread.h>
#include <io_utils.h>
int count = 0;
mtx_t mutex;
int Counter(void*arg)
{
for(int i = 0;i<100000;i++)
{
mtx_lock(&mutex);
count++;
mtx_unlock(&mutex);
/*
* int temp = count;
* count=temp+1;
* return temp;
* */
}
return 0;
}
int main()
{
mtx_init(&mutex,mtx_plain);
thrd_t t1;
thrd_t t2;
thrd_create(&t1,Counter,NULL);
thrd_create(&t2,Counter,NULL);
thrd_join(t1,NULL);
thrd_join(t2,NULL);
PRINT_INT(count);
mtx_destroy(&mutex);
return 0;
}
解决方法五 线程存储期
#include <stdio.h>
#include <tinycthread.h>
#include <io_utils.h>
_Thread_local int count = 0;//每个线程都有一个独立的副本
int Counter(int* arg)
{
for(int i = 0;i<100000;i++)
{
count+=*arg;
/*
* int temp = count;
* count=temp+1;
* return temp;
* */
}
PRINT_INT(count);
return 0;
}
int main()
{
thrd_t t1;
thrd_t t2;
int arg_1 = 1;
int arg_2 = 2;
thrd_create(&t1,Counter,&arg_1);
thrd_create(&t2,Counter,&arg_2);
thrd_join(t1,NULL);
thrd_join(t2,NULL);
PRINT_INT(count);
return 0;
//count: 100000
//count: 200000
//count: 0
}
解决方法六 tss
#include <stdio.h>
#include <tinycthread.h>
#include <io_utils.h>
tss_t count_key;
void MyFree(void*ptr)
{
PRINTLNF("free %#x",ptr);
free(ptr);
}
int Counter(int* arg)
{
int* count = malloc(sizeof(int));
*count = 0;
if(tss_set(count_key,count) == thrd_success) //如果绑定成功
{
for (int i = 0; i < 100000; i++) {
*count += *arg;
/*
* int temp = count;
* count=temp+1;
* return temp;
* */
}
}
PRINT_INT(*count);
PRINT_INT(*((int*)tss_get(count_key)));
return 0;
}
int main()
{
if(tss_create(&count_key,MyFree)==thrd_success)
{
thrd_t t1;
thrd_t t2;
int arg_1 = 1;
int arg_2 = 2;
thrd_create(&t1,Counter,&arg_1);
thrd_create(&t2,Counter,&arg_2);
//tss_delete(count_key); 如果在线程结束前删除,则不会调用MyFree,需要自己手动释放内存。
thrd_join(t1,NULL);
thrd_join(t2,NULL);
puts("t_1,t_2 ends");
tss_delete(count_key);
PRINTLNF("count_key delete");
}
return 0;
}
C语言线程安全问题的更多相关文章
- DP #1 Singleton Pattern线程安全问题
单例模式确保一个类只有一个实例,自行提供这个实例并向整个系统提供这个实例. 其中涉及到最主要的问题就是在多线程并发时线程安全问题. 单例模式的实现也有一个循序渐进的过程:1.最基本要求:每次从getI ...
- 【C#复习总结】探究各类数据结构(Array、List、Queue、Stack)及线程安全问题和yeild关键字
前言 先普及一下线程安全和类型安全 线程安全: 如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码.如果每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的 ...
- Java并发编程基础-线程安全问题及JMM(volatile)
什么情况下应该使用多线程 : 线程出现的目的是什么?解决进程中多任务的实时性问题?其实简单来说,也就是解决“阻塞”的问题,阻塞的意思就是程序运行到某个函数或过程后等待某些事件发生而暂时停止 CPU 占 ...
- ASP.NET MVC深入浅出系列(持续更新) ORM系列之Entity FrameWork详解(持续更新) 第十六节:语法总结(3)(C#6.0和C#7.0新语法) 第三节:深度剖析各类数据结构(Array、List、Queue、Stack)及线程安全问题和yeild关键字 各种通讯连接方式 设计模式篇 第十二节: 总结Quartz.Net几种部署模式(IIS、Exe、服务部署【借
ASP.NET MVC深入浅出系列(持续更新) 一. ASP.NET体系 从事.Net开发以来,最先接触的Web开发框架是Asp.Net WebForm,该框架高度封装,为了隐藏Http的无状态模 ...
- 被我们忽略的HttpSession线程安全问题
1. 背景 最近在读<Java concurrency in practice>(Java并发实战),其中1.4节提到了Java web的线程安全问题时有如下一段话: Servlets a ...
- Java多线程--线程安全问题的相关研究
在刚刚学线程的时候我们经常会碰到这么一个问题:模拟火车站售票窗口售票.代码如下: package cn.blogs.com.isole; /* 模拟火车站售票窗口售票,假设有50张余票 */ publ ...
- struts2学习笔记--线程安全问题小结
在说struts2的线程安全之前,先说一下,什么是线程安全?这是一个网友讲的, 如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码.如果每次运行结果和单线程运行的结果是一样 ...
- iOS中的线程安全问题
为了保证线程安全,不会因为多个线程访问造成资源抢夺,出现的运行结果的偏差问题,我们需要使用到线程同步技术,最常用的就是 @synchronized互斥锁(同步锁).NSLock.dispatch_se ...
- java 22 - 13 多线程之解决线程安全问题的实现方式2
上一章说了,解决线程安全问题的实现方式1是使用同步代码块 同时也知道了,同步代码块的锁对象是任意对象:(Object obj ; Demo d;)这些都行 那么,现在来说解决线程安全问题的实现方式2 ...
- java 22 - 12 多线程之解决线程安全问题的实现方式1
从上一章知道了多线程存在着线程安全问题,那么,如何解决线程安全问题呢? 导致出现问题的原因: A:是否是多线程环境 B:是否有共享数据 C:是否有多条语句操作共享数据 上一章的程序,上面那3条都具备, ...
随机推荐
- D. Required Length
D. Required Length 题意:给你一个长度n,一个数x,x每个后续状态可以由前一个状态乘以前一个状态的某一位上的数字得到,问最少多少步,能把x变成一个n位数.如果不能变成n位数,输出-1 ...
- 编译 windows 上的 qt 静态库
记录命令行编译过程: 针对 Qt 5.15.2 版本, 只需要 Source 文件就行 打开 x86 Native Tools Command Prompt for VS 2019,如果需要编译 x6 ...
- 启动HDFS伪分布式环境时报权限错误
问题描述 操作系统:Ubuntu18.04 LTS HDFS版本:hadoop-3.2.3 普通用户登录,参照官方文档在单机上安装伪分布式环境时,启动HDFS报权限错误. 具体报错信息如下: $ ./ ...
- locals()用法
views.py代码 def test(request): if request.method == 'GET': return render(request,'test.html') elif re ...
- @staticmethod/@classmethod/实例方法/@abstractmethod
from abc import ABCMeta, abstractmethod # 定义一个抽象类 class Person(metaclass=ABCMeta): name = "泰山&q ...
- AFNetworking整体框架简单整理
一.AFNetworking整体框架是怎样的 1.UIKit集成模块 UIKit 2.请求序列化 Serialization 3.响应序列化 Serialization 4.会话 NSURLSessi ...
- 【Azure 环境】当本地网络通过ER专线与Azure云上多个虚拟网络打通,如何通过特定的网络策略来限制本地部分网段访问云上虚拟机22端口?
问题描述 当本地网络通过ER专线与Azure云上多个虚拟网络打通,如何通过特定的网络策略来限制本地部分网段访问云上虚拟机22端口? 问题回答 根据文档调研,在ER线路服务的层面,是无法做网络策略来限制 ...
- 用 NetworkX + Gephi + Nebula Graph 分析<权力的游戏>人物关系(下篇)
在上一篇[1]中,我们通过 NetworkX 和 Gephi 展示了<权力的游戏>中的人物关系.在本篇中,我们将展示如何通过 NetworkX 访问图数据库 Nebula Graph. N ...
- 探索Terraform实践:优化基础设施管理
Terraform 是管理基础设施及代码(IaC)最常用的工具之一,它能使我们安全且可预测地对基础设施应用更改. Terraform作为一个强大的基础设施即代码工具,为开发人员和运维团队提供了一种简单 ...
- Hugging Face 表情包来啦!
小编有一个朋友,微信聊基本不回复文字,内容和情绪都化身成表情包直接回复,并且一气呵成.自带上下文衔接.你身边有这样的朋友吗? 作为梦想成为第一家以表情符号上市的公司,以及在社交平台发文 emoji 不 ...