<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                場景:在一個高并發的 Web 服務器中,要限制 IP 的頻繁訪問。現模擬 100 個 IP 同時并發訪問服務器,每個 IP 要重復訪問 1000 次。 每個 IP 三分鐘之內只能訪問一次。修改以下代碼完成該過程,要求能成功輸出 success:100 ~~~go 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) } ~~~ **解析** 該問題主要考察了并發情況下 map 的讀寫問題,而給出的初始代碼,又存在`for`循環中啟動`goroutine`時變量使用問題以及`goroutine`執行滯后問題。 因此,首先要保證啟動的`goroutine`得到的參數是正確的,然后保證`map`的并發讀寫,最后保證三分鐘只能訪問一次。 多 CPU 核心下修改`int`的值極端情況下會存在不同步情況,因此需要原子性的修改 int 值。 下面給出的實例代碼,是啟動了一個協程每分鐘檢查一下`map`中的過期`ip`,`for`啟動協程時傳參。 ~~~ package main import ( "context" "fmt" "sync" "sync/atomic" "time" ) type Ban struct { visitIPs map[string]time.Time lock sync.Mutex } func NewBan(ctx context.Context) *Ban { o := &Ban{visitIPs: make(map[string]time.Time)} go func() { timer := time.NewTimer(time.Minute * 1) for { select { case <-timer.C: o.lock.Lock() for k, v := range o.visitIPs { if time.Now().Sub(v) >= time.Minute*1 { delete(o.visitIPs, k) } } o.lock.Unlock() timer.Reset(time.Minute * 1) case <-ctx.Done(): return } } }() return o } func (o *Ban) visit(ip string) bool { o.lock.Lock() defer o.lock.Unlock() if _, ok := o.visitIPs[ip]; ok { return true } o.visitIPs[ip] = time.Now() return false } func main() { success := int64(0) ctx, cancel := context.WithCancel(context.Background()) defer cancel() ban := NewBan(ctx) wait := &sync.WaitGroup{} wait.Add(1000 * 100) for i := 0; i < 1000; i++ { for j := 0; j < 100; j++ { go func(j int) { defer wait.Done() ip := fmt.Sprintf("192.168.1.%d", j) if !ban.visit(ip) { atomic.AddInt64(&success, 1) } }(j) } } wait.Wait() fmt.Println("success:", success) } ~~~
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看