一道并发和锁的golang面试题
今天面试golang碰到了一道考并发和锁的题目,没有完成,所以把它记录下来,仅为以后复习。
场景:在一个高并发的web服务器中,要限制IP的频繁访问。现模拟100个IP同时并发访问服务器,每个IP要重复访问1000次。每个IP三分钟之内只能访问一次。修改以下代码完成该过程,要求能成功输出 success:100
package main
import (
"fmt"
"time"
)
type Ban struct {
visitIPs map[string]time.Time
}
func NewBan() *Ban {
return &Ban{visitIPs: make(map[string]time.Time)}
}
func (o *Ban) visit(ip string) bool {
if _, ok := o.visitIPs[ip]; ok {
return true
}
o.visitIPs[ip] = time.Now()
return false
}
func main() {
success := 0
ban := NewBan()
for i := 0; i < 1000; i++ {
for j := 0; j < 100; j++ {
go func() {
ip := fmt.Sprintf("192.168.1.%d", j)
if !ban.visit(ip) {
success++
}
}()
}
}
fmt.Println("success:", success)
}
以上代码有一些坑。当时也是没有做出来,回来请教一位大佬,得以解决。
package main
import (
"fmt"
"sync"
"sync/atomic"
"time"
)
type Ban struct {
visitIPs map[string]struct{}
}
func NewBan() *Ban {
return &Ban{visitIPs: make(map[string]struct{})}
}
//判断IP是否存在
func (o *Ban) visit(ip string) bool {
mapMutex.Lock()
defer mapMutex.Unlock()
if _, ok := o.visitIPs[ip]; ok {
return true
}
o.visitIPs[ip] = struct{}{}
go o.invalidAfter3Min(ip)
return false
}
// 3分钟后ip失效, 从map中移除. 因此ip再次访问时便可正常访问
func (o *Ban) invalidAfter3Min(ip string) {
time.Sleep(time.Minute * 3)
mapMutex.Lock()
visitIPs := o.visitIPs
delete(visitIPs, ip)
o.visitIPs = visitIPs
mapMutex.Unlock()
}
var mapMutex *sync.Mutex // mutex to avoid concurrent map writes
func main() {
mapMutex = new(sync.Mutex)
var success int64
ban := NewBan()
wg := new(sync.WaitGroup)
for i := 0; i < 1000; i++ {
for j := 0; j < 100; j++ {
wg.Add(1)
ipEnd := j
go func() {
defer wg.Done()
ip := fmt.Sprintf("192.168.1.%d", ipEnd)
if !ban.visit(ip) {
atomic.AddInt64(&success, 1)
}
}()
}
}
wg.Wait()
fmt.Println("success:", success)
}
主要用到了闭包,原子操作和锁实现
---------------------
作者:自傷無色丶
来源:CSDN
原文:https://blog.csdn.net/qq_28163175/article/details/75287877
版权声明:本文为博主原创文章,转载请附上博文链接!
一道并发和锁的golang面试题的更多相关文章
- Java 中的各种锁和 CAS + 面试题
Java 中的各种锁和 CAS + 面试题 如果说快速理解多线程有什么捷径的话,那本文介绍的各种锁无疑是其中之一,它不但为我们开发多线程程序提供理论支持,还是面试中经常被问到的核心面试题之一.因此下面 ...
- go golang 笔试题 面试题 笔试 面试
go golang 笔试题 面试题 笔试 面试 发现go的笔试题目和面试题目还都是比较少的,于是乎就打算最近总结一下.虽然都不难,但是如果没有准备猛地遇到了还是挺容易踩坑的. 就是几个简单的笔试题目, ...
- java 并发多线程 锁的分类概念介绍 多线程下篇(二)
接下来对锁的概念再次进行深入的介绍 之前反复的提到锁,通常的理解就是,锁---互斥---同步---阻塞 其实这是常用的独占锁(排它锁)的概念,也是一种简单粗暴的解决方案 抗战电影中,经常出现为了阻止日 ...
- java并发编程 | 锁详解:AQS,Lock,ReentrantLock,ReentrantReadWriteLock
原文:java并发编程 | 锁详解:AQS,Lock,ReentrantLock,ReentrantReadWriteLock 锁 锁是用来控制多个线程访问共享资源的方式,java中可以使用synch ...
- java锁机制的面试题
java锁机制的面试题 1.ABA问题 2.CAS乐观锁 3.synchronize实现原理 4.synchronize与lock的区别 5.volatile实现原理 6.乐观锁的业务场景及实现方式 ...
- Redis实现高并发分布式锁
分布式锁场景在分布式环境下多个操作需要以原子的方式执行首先启一个springboot项目,再引入redis依赖包: <!-- https://mvnrepository.com/artifa . ...
- Java并发 - (无锁)篇6
, 摘录自葛一鸣与郭超的 [Java高并发程序设计]. 本文主要介绍了死锁的概念与一些相关的基础类, 摘录自葛一鸣与郭超的 [Java高并发程序设计]. 无锁是一种乐观的策略, 它假设对资源的访问是没 ...
- Java多线程并发08——锁在Java中的应用
前两篇文章中,为各位带来了,锁的类型及锁在Java中的实现.接下来本文将为各位带来锁在Java中的应用相关知识.关注我的公众号「Java面典」了解更多 Java 相关知识点. 锁在Java中主要应用还 ...
- 从源码学习Java并发的锁是怎么维护内部线程队列的
从源码学习Java并发的锁是怎么维护内部线程队列的 在上一篇文章中,凯哥对同步组件基础框架- AbstractQueuedSynchronizer(AQS)做了大概的介绍.我们知道AQS能够通过内置的 ...
随机推荐
- Hnoi2017试题泛做
Day1 4825: [Hnoi2017]单旋 注意到二叉查找树的一个性质:其中序遍历就是所有元素按权值排序的顺序. 所以我们可以离线地把这棵树的中序遍历求出来.然后我们在插入的时候就可以用一个set ...
- 小程序上传wx.uploadFile - 小程序请假-请求
小程序上传wx.uploadFile UploadTask wx.uploadFile(Object object) 将本地资源上传到服务器.客户端发起一个 HTTPS POST 请求,其中 cont ...
- [LOJ2538][PKUWC2018]Slay the Spire:DP
分析 学会新姿势!我们可以通过调整DP顺序来体现选取物品的优先顺序! 显然选取强化牌的最优策略是倍数从高到低,能选就选,最多选\(k-1\)张,选取攻击牌的最优策略是伤害从高到低,尽量少选,但最少选\ ...
- JAVASCRIPT试题及答案
1.用jQuery编程实现获取选中复选框值的函数abc. <body> <input type="checkbox" name="aa" va ...
- H5自定义video功能与样式处理
H5的video非常简单,方便,有时我们可能需要自己来设置样式来自定义的video,自定义的话我们需要对功能进行一些处理,这里常用的功能几乎是都用到了,第一次练习代码很累赘,之后会慢慢改进. 常用的一 ...
- Wordpress可以用来做什么?
WordPress本身只是一款开源的.基于PHP的博客软件,但是由于WordPress的源码开源.结构优良.插件丰富.主题繁多,以至于是 WordPress成为世界上最流行的博客程序.<Word ...
- Struts2拦截器和过滤器的区别?
①过滤器依赖于Servlet容器,而拦截器不依赖于Servlet容器. ②Struts2 拦截器只能对Action请求起作用,而过滤器则可以对几乎所 有请求起作用. ③拦截器可以访问 Action上下 ...
- vue项目使用cropperjs制作图片剪裁,压缩组件
项目中裁剪图片效果 代码部分:(将上传部分 封装成一个组件直接调用当前组件) <template> <div id="demo"> <!-- 遮罩层 ...
- TCP 之 TCP首部
TCP首部图 TCP首部说明 源端口,目的端口 用于寻找发送端和接收端应用进程.(源IP,源端口,目的IP,目的端口) 四元组确定唯一一个TCP连接:(IP,端口)也称为一个插口(socket): 序 ...
- 学习曲线(learning curves)
假定假设函数为一个二次函数,只是参数未定: 每给定一个样本大小,就能训练出对应的假设函数,从而利用这个假设函数可以计算出Jtrain(仍然在之前拿来训练的那些样本里面),然后将训练好的假设函数用在全部 ...