- vừa được xem lúc

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

0 0 22

Người đăng: Phượng Sồ

Theo Viblo Asia

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!

Bình luận

Bài viết tương tự

- vừa được xem lúc

gRPC - Nó là gì và có nên sử dụng hay không?

Nhân một ngày rảnh rỗi, mình ngồi đọc lại RPC cũng như gRPC viết lại để nhớ lâu hơn. Vấn đề là gì và tại sao cần nó .

0 0 131

- vừa được xem lúc

Embedded Template in Go

Getting Start. Part of developing a web application usually revolves around working with HTML as user interface.

0 0 56

- vừa được xem lúc

Tạo Resful API đơn giản với Echo framework và MySQL

1. Giới thiệu.

0 0 60

- vừa được xem lúc

Sử dụng goquery trong golang để crawler thông tin các website Việt Nam bị deface trên mirror-h.org

. Trong bài viết này, mình sẽ cùng mọi người khám phá một package thu thập dữ liệu có tên là goquery của golang. Mục tiêu chính của chương trình crawler này sẽ là lấy thông tin các website Việt Nam bị deface (là tấn công, phá hoại website, làm thay đổi giao diện hiển thị của một trang web, khi người

0 0 237

- vừa được xem lúc

Tạo ứng dụng craw dữ liệu bing với Golang, Mysql driver

Chào mọi người . Lâu lâu ta lại gặp nhau 1 lần, để tiếp tục series chia sẻ kiến thức về tech, hôm nay mình sẽ tìm hiểu và chia sẻ về 1 ngôn ngữ đang khá hot trong cộng đồng IT đó là Golang.

0 0 75

- vừa được xem lúc

Golang: Rest api and routing using MUX

Routing with MUX. Let's create a simple CRUD api for a blog site. # All . GET articles/ .

0 0 54