今天面试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面试题的更多相关文章

  1. Java 中的各种锁和 CAS + 面试题

    Java 中的各种锁和 CAS + 面试题 如果说快速理解多线程有什么捷径的话,那本文介绍的各种锁无疑是其中之一,它不但为我们开发多线程程序提供理论支持,还是面试中经常被问到的核心面试题之一.因此下面 ...

  2. go golang 笔试题 面试题 笔试 面试

    go golang 笔试题 面试题 笔试 面试 发现go的笔试题目和面试题目还都是比较少的,于是乎就打算最近总结一下.虽然都不难,但是如果没有准备猛地遇到了还是挺容易踩坑的. 就是几个简单的笔试题目, ...

  3. java 并发多线程 锁的分类概念介绍 多线程下篇(二)

    接下来对锁的概念再次进行深入的介绍 之前反复的提到锁,通常的理解就是,锁---互斥---同步---阻塞 其实这是常用的独占锁(排它锁)的概念,也是一种简单粗暴的解决方案 抗战电影中,经常出现为了阻止日 ...

  4. java并发编程 | 锁详解:AQS,Lock,ReentrantLock,ReentrantReadWriteLock

    原文:java并发编程 | 锁详解:AQS,Lock,ReentrantLock,ReentrantReadWriteLock 锁 锁是用来控制多个线程访问共享资源的方式,java中可以使用synch ...

  5. java锁机制的面试题

    java锁机制的面试题 1.ABA问题 2.CAS乐观锁 3.synchronize实现原理 4.synchronize与lock的区别 5.volatile实现原理 6.乐观锁的业务场景及实现方式 ...

  6. Redis实现高并发分布式锁

    分布式锁场景在分布式环境下多个操作需要以原子的方式执行首先启一个springboot项目,再引入redis依赖包: <!-- https://mvnrepository.com/artifa . ...

  7. Java并发 - (无锁)篇6

    , 摘录自葛一鸣与郭超的 [Java高并发程序设计]. 本文主要介绍了死锁的概念与一些相关的基础类, 摘录自葛一鸣与郭超的 [Java高并发程序设计]. 无锁是一种乐观的策略, 它假设对资源的访问是没 ...

  8. Java多线程并发08——锁在Java中的应用

    前两篇文章中,为各位带来了,锁的类型及锁在Java中的实现.接下来本文将为各位带来锁在Java中的应用相关知识.关注我的公众号「Java面典」了解更多 Java 相关知识点. 锁在Java中主要应用还 ...

  9. 从源码学习Java并发的锁是怎么维护内部线程队列的

    从源码学习Java并发的锁是怎么维护内部线程队列的 在上一篇文章中,凯哥对同步组件基础框架- AbstractQueuedSynchronizer(AQS)做了大概的介绍.我们知道AQS能够通过内置的 ...

随机推荐

  1. confluence -- 命令行备份还原

    备份:confluence每日凌晨2:00都在 /data/atlassian/application-data/confluence/backups/ 下生成备份包,其中包括文档,附件,用户 还原: ...

  2. AcWing:246. 区间最大公约数(线段树 + 增量数组(树状数组) + 差分序列)

    给定一个长度为N的数列A,以及M条指令,每条指令可能是以下两种之一: 1.“C l r d”,表示把 A[l],A[l+1],…,A[r] 都加上 d. 2.“Q l r”,表示询问 A[l],A[l ...

  3. springboot+mybatis 使用事务

    一.一些概念 声明式的事务管理是基于AOP的,在springboot中可以通过@Transactional注解的方式获得支持,这种方式的优点是: 1)非侵入式,业务逻辑不受事务管理代码的污染. 2)方 ...

  4. MongoDB4和MysSQL5.7的读/写和事务处理速度简单对比

    系统环境: Ubuntu 18.04 数据库 MysSQL5.7/MongoDB4.0 插入的数据为随机生产,不重复. MySQL使用的连接库是 sqlalchemyMongoDB使用的连接库是pym ...

  5. CountDownLatch和CyclicBarrier的比较

    1.CountDownLatch是线程组之间的等待,即一个(或多个)线程等待N个线程完成某件事情之后再执行:而CyclicBarrier则是线程组内的等待,即每个线程相互等待,即N个线程都被拦截之后, ...

  6. Java多线程深度探索

    线程 1.优先级 每个线程有一个优先级,更高优先级的线程优先运行,优先的意思是只是在分配cpu时间段的时候,得到的概率高一些.当在某个线程创建一个新的线程,这个线程有与创建线程相同的优先级.setPr ...

  7. 【转】jQuery - 同时添加click和dblclick事件

    特别提示:本人博客部分有参考网络其他博客,但均是本人亲手编写过并验证通过.如发现博客有错误,请及时提出以免误导其他人,谢谢!欢迎转载,但记得标明文章出处:http://www.cnblogs.com/ ...

  8. 【转】HLS视频点播&直播初探

    特别提示:本人博客部分有参考网络其他博客,但均是本人亲手编写过并验证通过.如发现博客有错误,请及时提出以免误导其他人,谢谢!欢迎转载,但记得标明文章出处:http://www.cnblogs.com/ ...

  9. MSO Transponder 页面开发思路

    1. 确定Transponder开发页面分类,定义负责模块 2. 定义模块页面布局 3. 选择页面各数据对应的控件类型 4. 选定控件对应set/get所用方式 快捷键链接设置: http://www ...

  10. oracle取差值集合

    Oracle Minus关键字 SQL中的MINUS关键字 SQL中有一个MINUS关键字,它运用在两个SQL语句上,它先找出第一条SQL语句所产生的结果,然后看这些结果有没有在第二个SQL语句的结果 ...