欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

golang并發(fā)之使用sync.Pool優(yōu)化性能

 更新時間:2023年10月24日 09:30:04   作者:jefffff  
在Go提供如何實現對象的緩存池功能,常用一種實現方式是sync.Pool,?其旨在緩存已分配但未使用的項目以供以后重用,從而減輕垃圾收集器(GC)的壓力,下面我們就來看看具體操作吧

簡介

在Go提供如何實現對象的緩存池功能?常用一種實現方式是:sync.Pool, 其旨在緩存已分配但未使用的項目以供以后重用,從而減輕垃圾收集器(GC)的壓力。

快速使用

sync.Pool的結構也比較簡單,常用的方法有Get、Put

type Pool struct {
    local     unsafe.Pointer // local fixed-size per-P pool, actual type is [P]poolLocal
    localSize uintptr        // size of the local array

    victim     unsafe.Pointer // local from previous cycle
    victimSize uintptr        // size of victims array

    // New optionally specifies a function to generate
    // a value when Get would otherwise return nil.
    // It may not be changed concurrently with calls to Get.
    New func() any
}
func (p *Pool) Get() any  
func (p *Pool) Put(x any) 

接著,通過一個簡單的例子,來看看是如何使用的

package main

import (
    "fmt"
    "sync"
)

type Object struct {
    ID int
    // ...
}

func main() {
    // 1.創(chuàng)建一個sync.Pool對象
    pool := &sync.Pool{
       New: func() interface{} {
          fmt.Println("Creating a new object")
          return &Object{}
       },
    }
    // 2.pool.Get()方法從池中獲取一個對象。如果池中有可用的對象,Get()方法將返回其中一個;否則,它將返回一個新創(chuàng)建的對象
    obj := pool.Get().(*Object)
    // 3.操作對象
    obj.ID = 1
    // 4.調用pool.Put()方法將對象放回池中
    pool.Put(obj)
    objBar := pool.Get().(*Object)
    fmt.Println("Object ID:", objBar.ID)
}

實踐應用

在之前的文章中有提到的享元模式設計模式:flyweight(享元)的在棋牌游戲的應用的案例。今天我們使用sync.Pool對該方案進行優(yōu)化。 觀察在棋牌游戲的代碼,雖然解決了每次都要New一個對象的問題,但還存在幾個優(yōu)化點:

  • 不能只能緩存特定的棋牌室類型對象;
  • 并發(fā)安全問題

原來是通過Factory工廠+Map實現享元模式,截取其中部分代碼如下

package design_mode

import "fmt"

var chessPieceUnit = map[int]*ChessPiece{
	1: {
		Name:  "車",
		Color: "紅",
		PositionX: 1,
		PositionY: 11,
	},
	2: {
		Name:  "馬",
		Color: "黑",
		PositionX: 2,
		PositionY: 2,
	},
	// 其他棋子
}

func NewChessPieceUnitFactory() *ChessBoard {
	board := &ChessBoard{Cards: map[int]*ChessPiece{}}
	for id := range chessPieceUnit {
		board.Cards[id] = chessPieceUnit[id]
	}
	return board
}

1.重構Factory

接著,我們同sync.Pool修改一下Factory的實現:

pool := &sync.Pool{
    New: func() interface{} {
       fmt.Println("Creating a new object")
       return NewChessBoard()
    },
}

game1 := pool.Get().(*ChessBoard)
game2 := pool.Get().(*ChessBoard)
fmt.Println(game1)
fmt.Println(game2)
fmt.Println(game1.Cards[0] == game2.Cards[0]) 

2. 并發(fā)安全問題

2.1 修改模型

為了方便觀察,給每個房間(棋牌室)增加一個創(chuàng)建時間

type ChessBoard struct {
    Cards map[int]*ChessPiece
    Time  time.Time
} 

2.2 并發(fā)測試

啟動多個goroutine進行測試

func main() {
    pool := &sync.Pool{
       New: func() interface{} {
          fmt.Println("Creating a new object")
          return NewChessBoard()
       },
    }
    var wg sync.WaitGroup
    for i := 0; i < 10; i++ {
       wg.Add(1)
       go func(id int) {
          defer wg.Done()
          obj := pool.Get().(*ChessBoard)
          obj.Time = time.Now()
          pool.Put(obj)
          fmt.Printf("Object ID: %v\n", obj.Time)
       }(i)
    }
    wg.Wait()
} 

輸出如下:

Creating a new object
Creating a new object
Object ID: 2023-10-22 15:41:50.309343 +0800 CST m=+0.003511901
Object ID: 2023-10-22 15:41:50.3117423 +0800 CST m=+0.005911201
Object ID: 2023-10-22 15:41:50.3117423 +0800 CST m=+0.005911201
Object ID: 2023-10-22 15:41:50.3117423 +0800 CST m=+0.005911201
Object ID: 2023-10-22 15:41:50.3117423 +0800 CST m=+0.005911201
Object ID: 2023-10-22 15:41:50.3117423 +0800 CST m=+0.005911201
Object ID: 2023-10-22 15:41:50.3117423 +0800 CST m=+0.005911201
Object ID: 2023-10-22 15:41:50.3117423 +0800 CST m=+0.005911201
Object ID: 2023-10-22 15:41:50.3117423 +0800 CST m=+0.005911201
Object ID: 2023-10-22 15:41:50.3117423 +0800 CST m=+0.005911201

可見,在多個goroutine的并發(fā)情況下,是安全,另外可以觀察到,sync.Pool沒有一直【Creating a new object】去New很多棋牌室。

小結

sync.Pool是Go語言標準庫中的一個類型,它提供了對象的緩存池功能。它的主要用途是存儲那些可以被復用的臨時對象,以便在需要時快速獲取,而不是每次都進行新的對象分配。且多個 goroutine 同時使用 Pool 是安全的。

本文簡述了sync.Pool的基礎使用,以及了如何使用其對實踐棋牌室游戲的案例進行優(yōu)化過程。

以上就是golang并發(fā)之使用sync.Pool優(yōu)化性能的詳細內容,更多關于go sync.Pool的資料請關注腳本之家其它相關文章!

相關文章

  • Go語言基礎go fmt命令使用示例詳解

    Go語言基礎go fmt命令使用示例詳解

    這篇文章主要為大家介紹了Go語言基礎go fmt命令的使用示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步
    2021-11-11
  • Go log庫的使用示例詳解

    Go log庫的使用示例詳解

    Go語言內置的log庫提供了基本的日志記錄功能,支持日志的格式化輸出、設置日志前綴、配置輸出位置等,可以通過標準logger或創(chuàng)建新的Logger對象來使用,log庫簡單易用,但功能有限,可能需要配合第三方日志庫如logrus、zap等來滿足復雜需求
    2024-09-09
  • Go?gRPC教程實現Simple?RPC

    Go?gRPC教程實現Simple?RPC

    這篇文章主要為大家介紹了Go?gRPC教程實現Simple?RPC示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-06-06
  • golang框架中跨服務的最佳通信協議和工具

    golang框架中跨服務的最佳通信協議和工具

    在 go 框架中實現跨服務通信的最佳實踐包括使用 grpc(適用于低延遲高吞吐量)、http 客戶端(適用于 restful api)和消息隊列(適用于異步解耦通信),在選擇通信方式時,應考慮服務交互模式、性能要求和部署環(huán)境等因素
    2024-06-06
  • Go語言學習技巧之命名規(guī)范

    Go語言學習技巧之命名規(guī)范

    最近在學習go語言,發(fā)現了不少需要整理的知識點,所以整理下分享出來,下面這篇文章主要給大家介紹了關于Go語言學習技巧之命名規(guī)范的相關資料,文中通過示例代碼介紹的非常詳細,需要的朋友可以參考借鑒,下面來一起看看吧。
    2017-12-12
  • go-micro微服務JWT跨域認證問題

    go-micro微服務JWT跨域認證問題

    JWT 以 JSON 對象的形式安全傳遞信息。因為存在數字簽名,因此所傳遞的信息是安全的,這篇文章主要介紹了go-micro微服務JWT跨域認證,需要的朋友可以參考下
    2023-01-01
  • Go語言庫系列之dotsql詳解

    Go語言庫系列之dotsql詳解

    這篇文章主要介紹了Go語言庫系列之dotsql的相關知識,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-04-04
  • 用golang如何替換某個文件中的字符串

    用golang如何替換某個文件中的字符串

    這篇文章主要介紹了用golang實現替換某個文件中的字符串操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-04-04
  • 利用golang的字符串解決leetcode翻轉字符串里的單詞

    利用golang的字符串解決leetcode翻轉字符串里的單詞

    這篇文章主要介紹了利用golang的字符串解決leetcode翻轉字符串里的單詞,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-12-12
  • Golang中文件目錄操作的實現步驟詳解

    Golang中文件目錄操作的實現步驟詳解

    在Golang中,文件目錄是指計算機文件系統(tǒng)中的文件夾或目錄。目錄是用于組織和存儲文件的一種方式,可以包含文件和其他子目錄,本文主要介紹了Golang中文件目錄操作的實現方法,需要的朋友可以參考下
    2023-05-05

最新評論