[Golang] Channel trong golang và use case – part III

Mở đầu Tiếp tục series, hôm nay là một buổi chia sẽ của tôi về use case của channel trong GO. Let’s go, guys! Use case 2: Implement semaphore pattern trong golang Như mọi lần chúng ta sẽ đi làm vài vòng qua định nghĩa. Theo wikipedia, ta sẽ có định nghĩa hoàn chỉnh về

Mở đầu

  • Tiếp tục series, hôm nay là một buổi chia sẽ của tôi về use case của channel trong GO. Let’s go, guys!

Use case 2: Implement semaphore pattern trong golang

  • Như mọi lần chúng ta sẽ đi làm vài vòng qua định nghĩa. Theo wikipedia, ta sẽ có định nghĩa hoàn chỉnh về semaphore như sau:
    semaphore is a variable or abstract data type used to control access to a common resource by multiple threads and avoid critical section problems in a concurrent system such as a multitasking operating system.
  • Trong một currency system, resource sẽ bị truy cập đồng thời bởi nhiều process. Và semarphore được xem như là một cơ chế để quản lý các truy cập các resource đó.
  • Những ứng dụng của semaphore mà chúng ta có thể thấy là:
    • Limit database connection pool
    • Networking connection throttling
    • Limiting concurrent access to resources such as a disk
  • Sau đây là một simple implement của semaphore trong golang dựa vào đặc tính của channel
    images.jpeg
    • Giả lập chúng ta có N request cần được xử lý một cách đồng thời. Mỗi request chúng ta cần số M thời gian nhất định để xử lí.
      func main(){
          numberOfRequest := 10 
          for i := 0; i < numberOfRequest; i++ {
              go handleRequest(strconv.Itoa(i))
          }
      
          /* sleep to see what happen */
          time.Sleep(time.Second * 12)
      }
      
      func handleRequest(requestName string) {
          fmt.Printf("%v: request %v: is accessing resource n", time.Now().Format("15:04:05"), requestName)
          time.Sleep(time.Second * 3)
      }
      result:
          16:14:06: request 4: is accessing resource
          16:14:06: request 9: is accessing resource
          16:14:06: request 5: is accessing resource
          16:14:06: request 6: is accessing resource
          16:14:06: request 7: is accessing resource
          16:14:06: request 8: is accessing resource
          16:14:06: request 1: is accessing resource
          16:14:06: request 3: is accessing resource
          16:14:06: request 0: is accessing resource
          16:14:06: request 2: is accessing resource
      
    • Chúng ta có thể thấy cùng một lúc tai giây 16:14:05 có đang có 10 request đang truy cập resource. Tiếp theo, dựa vào đặc tính block goroutine hiện tai của buffer chanel khi sức chứa của nó bị quá tải, chúng ta sẽ chỉ cho phép tối đa là 3 truy cập cùng lúc trên resource.
       func main(){
           maxConcurrency := 3
           sem := make(chan struct{}, maxConcurrency)
      
           numberOfRequest := 10 
           for i := 0; i < numberOfRequest; i++ {
      
               sem <- struct{}{} // acquire the resource
      
               go handleRequest(strconv.Itoa(i))
           }
      
           /* sleep to see what happen */
           time.Sleep(time.Second * 12)
       }
      
       func handleRequest(requestName string) {
           fmt.Printf("%v: request %v: is accessing resource n", time.Now().Format("15:04:05"), requestName)
           time.Sleep(time.Second * 3)
       }
       
       result:
           16:30:30: request 1: is accessing resource
           16:30:30: request 0: is accessing resource
           16:30:30: request 2: is accessing resource
           fatal error: all goroutines are asleep - deadlock!
      
           goroutine 1 [chan send]:
           main.main()
                   D:/projects/semaphores/main.go:15 +0x59
           exit status 2
      
      
    • Deadlock xuất hiện bởi vì không có goroutine nào đến giải phóng space cho channel. Giống như ở siêu thị, một hàng dài khách hàng đang đợi tính tiền và cashier machine bổng dưng dở chứng, dẩn đến một tình trạng ứ đọng. Để giải quyết, chúng ta phải làm thêm 1 nhiệm vụ là: release resource khi đã xử dụng xong.
      ...
      func handleRequest(requestName string, sem chan struct{}) {
          defer release(sem)
      
          fmt.Printf("%v: request %v: is accessing resource n", time.Now().Format("15:04:05"), requestName)
          time.Sleep(time.Second * 3)
      }
      
      func release(sem chan struct{}) {
          <-sem
      }
      
    • Running và see what happen!
        16:45:24: request 0: is accessing resource
        16:45:24: request 1: is accessing resource
        16:45:24: request 2: is accessing resource
        16:45:27: request 3: is accessing resource
        16:45:27: request 4: is accessing resource
        16:45:27: request 5: is accessing resource
        16:45:30: request 6: is accessing resource
        16:45:30: request 7: is accessing resource
        16:45:30: request 8: is accessing resource
        16:45:33: request 9: is accessing resource
      

      Request lúc này đã được seperate thành từng nhóm gồm 3 request và truy cập vào giây 24, 27, 30 và 33 giống như nguyên lý của sermaphore.

Tạm kết

  • Dựa vào phần trình bày ở trên, hi vọng có thể giúp bạn hiểu thêm về semarphore pattern. Bạn hoàn toàn có thể tùy biến nó để giải quyết một số bài toán tương tự như shushi bar, sleep barber hay bài toán craw url with only 5 workers mà mình đã giới thiệu ở part II .
  • Ngoài ra, golang cũng có một semarphore package chính thức tại đây
    github .
  • Thanks for reading! See you on next part!

Nguồn: viblo.asia

Bài viết liên quan

Thay đổi Package Name của Android Studio dể dàng với plugin APR

Nếu bạn đang gặp khó khăn hoặc bế tắc trong việc thay đổi package name trong And

Lỗi không Update Meta_Value Khi thay thế hình ảnh cũ bằng hình ảnh mới trong WordPress

Mã dưới đây hoạt động tốt có 1 lỗi không update được postmeta ” meta_key=

Bài 1 – React Native DevOps các khái niệm và các cài đặt căn bản

Hướng dẫn setup jenkins agent để bắt đầu build mobile bằng jenkins cho devloper an t

Chuyển đổi từ monolith sang microservices qua ví dụ

1. Why microservices? Microservices là kiến trúc hệ thống phần mềm hướng dịch vụ,