.NET 固定时间窗口算法实现(无锁线程安全)
一.前言
最近有一个生成 APM TraceId 的需求,公司的APM系统的 TraceId 的格式为:APM AgentId+毫秒级时间戳+自增数字,根据此规则生成的 Id 可以保证全局唯一(有 NTP 时间同步),前两个字段好说,最后一个字段也不复杂,我的想法是按秒来进行自增。比如说1秒的时候,自增计数为100,在2秒的时候会重置为0,然后进行自增。其实这个思想就是固定时间窗口算法,这个算法一般常用在限流、Id生成器等场景。
二.代码实现
long _currentTime;
long _current;
public long FixedWindow()
{
var now = DateTimeOffset.Now.ToUnixTimeSeconds();
var ct = Interlocked.Read(ref _currentTime);
if (now > ct)
{
if (Interlocked.CompareExchange(ref _currentTime, now, ct)==ct)
{
return Interlocked.Exchange(ref _current, 0);
}
}
return Interlocked.Increment(ref _current);
}
代码没多少,每调用一次就返回计数,采用的 C# CAS API Interlocked ,保证每个计数操作都是原子操作,从而达到无锁。
测试代码,使用10个线程并发调用,每个线程调用 1w次,最终期望计数应该是10w。
private static long _currentTime;
private static long _current;
private static Semaphore _semaphore = new Semaphore(0, 10);
static void Main(string[] args)
{
_currentTime = DateTimeOffset.Now.ToUnixTimeSeconds();
_current = 0;
for (int i = 0; i < 10; i++)
{
Task.Factory.StartNew(() =>
{
for (int j = 0; j < 10000; j++)
{
FixedWindow();
}
_semaphore.Release(1);
});
}
for (int i = 0; i < 10; i++)
{
_semaphore.WaitOne();
}
Console.WriteLine(_current);
Console.WriteLine("sleep 2s");
Thread.Sleep(2000);
Console.WriteLine(FixedWindow());
}
执行结果:

符合预期,10线程的计数在 1s 内能执行完毕,所以最终计数是10w,然后sleep 2s,重置计数,再次调用就返回了 1
三.资料
本文 Demo 代码:github
.NET 固定时间窗口算法实现(无锁线程安全)的更多相关文章
- Sentinel-Go 源码系列(三)滑动时间窗口算法的工程实现
要说现在工程师最重要的能力,我觉得工程能力要排第一. 就算现在大厂面试经常要手撕算法,也是更偏向考查代码工程实现的能力,之前在群里看到这样的图片,就觉得很离谱. 算法与工程实现 在 Sentinel- ...
- 时间轮算法在Netty和Kafka中的应用,为什么不用Timer、延时线程池?
大家好,我是yes. 最近看 Kafka 看到了时间轮算法,记得以前看 Netty 也看到过这玩意,没太过关注.今天就来看看时间轮到底是什么东西. 为什么要用时间轮算法来实现延迟操作? 延时操作 Ja ...
- Sentinel滑动窗口算法
在前面搞清楚了Sentinel的使用后,大致理了一下Sentinel的责任链,搞清楚了这个,基本就已经梳理清楚sentinel-core模块的大部分内容,顺着这条链路可以继续梳理很多东西. 知其然.知 ...
- 时间轮算法(TimingWheel)是如何实现的?
前言 我在2. SOFAJRaft源码分析-JRaft的定时任务调度器是怎么做的?这篇文章里已经讲解过时间轮算法在JRaft中是怎么应用的,但是我感觉我并没有讲解清楚这个东西,导致看了这篇文章依然和没 ...
- 威胁预警|Solr velocity模板注入远程命令执行已加入watchbog武器库,漏洞修补时间窗口越来越短
概述 近日,阿里云安全团队监测到挖矿团伙watchbog更新了其使用的武器库,增加了最新Solr Velocity 模板注入远程命令执行漏洞的攻击方式,攻击成功后会下载门罗币挖矿程序进行牟利.建议用户 ...
- Chromium的无锁线程模型C++代码示例
引言 作者:程序员bingo,主要关注客户端架构设计.性能优化.崩溃处理,有多年的Chromium浏览器开发经验. 多线程一直是软件开发中最容易出问题的环节,很多的崩溃.卡死问题都与多线程有关.在常用 ...
- C#固定时间执行指定事件(观察者模式+异步委托)
最近有个项目需要每天固定的时间去执行指定的事件,发现网上关于这样的文章比较少,而且比较散.通过学习了几篇文章后终于实现了这个功能,在此也特别感谢这些文章的作者们,这也是我第一次在园子里面发文章,望多指 ...
- Flink流处理的时间窗口
Flink流处理的时间窗口 对于流处理系统来说,流入的消息是无限的,所以对于聚合或是连接等操作,流处理系统需要对流入的消息进行分段,然后基于每一段数据进行聚合或是连接等操作. 消息的分段即称为窗口,流 ...
- kafka传数据到Flink存储到mysql之Flink使用SQL语句聚合数据流(设置时间窗口,EventTime)
网上没什么资料,就分享下:) 简单模式:kafka传数据到Flink存储到mysql 可以参考网站: 利用Flink stream从kafka中写数据到mysql maven依赖情况: <pro ...
随机推荐
- 关于 this.$route.meta.operations.includes('delete') 取不到值的问题
原因是:src/mock/api/sys.login.js中定义的路径 要与src/router/modules/下定义的路由要一致 作用this.$route.matched可以查看匹配信息 来自为 ...
- [网络编程] 自己构建一个cgi.FieldStorage()的对象
问题描述: 通常cgi.FieldStorage()返回一个类似于Python字典的对象. 在cgi框架中必须通过浏览器发送表单过来才能接受消息 那么我该怎么进行本地调试呢? 或者说在没有搭建好一整套 ...
- ch01系统基础信息模块详解
第1章 系统基础信息模块详解 1.1 系统性能信息模块 psutil 解决VMWare在Windows10的安装问题: 安装VC Redistributable 2017 解决虚拟机的上网问题:修改V ...
- webSocket 使用 HttpSession 的数据配置与写法
1.前言 webSoket 无法获取 HttpSession ,使用就更谈不上了 !!! 2解决过程 使用 configurator 注入即可 (1) 配置一个类 1 package cn.c ...
- elasticsearch拼写纠错之Term Suggester
一.什么是拼写纠错 拼写纠错就是搜索引擎可以智能的感知用户输入关键字的错误,并使用纠正过的关键字进行搜索展示给用户:拼写纠错是一种改善用户体验的功能: elasticsearch提供了以下不同类型的s ...
- Javascript面向对象——创建对象、构造函数的原型
Javascript面向对象--创建对象.构造函数的原型 其实:JavaScript中的创建类,就是创建一个构造函数,在创建对象时用到new这个关键字, 一.创建对象 1.函数创建对象 functio ...
- C# 获取DPI例子
public static float GetDpiX() { System.Windows.Forms.Panel p = new System.Windows.Forms.Panel(); Sys ...
- 【解决了一个小问题】alert manager中的cluster.advertise-address参数是什么意思?
如果在启动 alert manager的时候,不填写参数: /usr/bin/alertmanager --config.file=/etc/alert_manager/alertmanager.ya ...
- Ajax_axios发送ajax请求
Ajax_axios发送ajax请求 这篇笔记主要讲一下axios基本的发送ajax请求的方法 axios在当前的前端行业里面是用的比较热门的一个 下面给大家分享一下它axios的一个基本用法 这段代 ...
- Linux深入探索01-stty与键盘信号
----- 最近更新[2021-12-20]----- 一.简介 最初的 Unix 设定假定人们使用终端连接主机计算机.30多年过去后,情况依然如此,即便是在自己的PC机上运行Unix.多年以来,终端 ...