go: Lock/Mutex Pattern

项目结构:

Go 复制代码
/*
# 版权所有  2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:Lock/Mutex Pattern 互斥锁(Mutex)
# Author    : geovindu,Geovin Du 涂聚文.
# IDE       : goLang 2024.3.6 go 26.2
# os        : windows 10
# database  : mysql 9.0 sql server 2019, postgreSQL 17.0  Oracle 21c Neo4j
# Datetime  : 2026/5/11 22:00
# User      :  geovindu
# Product   : GoLand
# Project   : godesginpattern
# File      : jewelry.go
*/
package domain
 
import "sync"
 
// Jewelry 珠宝领域模型(线程安全,互斥锁完全封装)
type Jewelry struct {
    mu    sync.Mutex // 私有锁:外部无法访问,绝对安全
    ID    string
    Name  string
    Stock int
}
 
// NewJewelry 创建珠宝实例
func NewJewelry(id, name string, stock int) *Jewelry {
    return &Jewelry{
        ID:    id,
        Name:  name,
        Stock: stock,
    }
}
 
// Sell 销售:线程安全扣减库存
func (j *Jewelry) Sell(num int) (bool, string) {
    j.mu.Lock()
    defer j.mu.Unlock()
 
    if j.Stock < num {
        return false, "库存不足,无法销售"
    }
    j.Stock -= num
    return true, "销售成功"
}
 
// Replenish 补货:线程安全增加库存
func (j *Jewelry) Replenish(num int) (bool, string) {
    j.mu.Lock()
    defer j.mu.Unlock()
 
    j.Stock += num
    return true, "补货成功"
}
 
// GetStock 线程安全查询库存
func (j *Jewelry) GetStock() int {
    j.mu.Lock()
    defer j.mu.Unlock()
    return j.Stock
}
Go 复制代码
/*
# 版权所有  2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:Lock/Mutex Pattern 互斥锁(Mutex)
# Author    : geovindu,Geovin Du 涂聚文.
# IDE       : goLang 2024.3.6 go 26.2
# os        : windows 10
# database  : mysql 9.0 sql server 2019, postgreSQL 17.0  Oracle 21c Neo4j
# Datetime  : 2026/5/11 22:01
# User      :  geovindu
# Product   : GoLand
# Project   : godesginpattern
# File      : jewelry_repo.go
*/
package repository
 
import (
    "godesginpattern/mutex/domain"
    "sync"
)
 
// JewelryRepository 珠宝存储接口(可扩展MySQL/Redis)
type JewelryRepository interface {
    Save(j *domain.Jewelry)
    GetByID(id string) *domain.Jewelry
}
 
// InMemoryJewelryRepo 内存实现(生产可替换为MySQL)
type InMemoryJewelryRepo struct {
    data map[string]*domain.Jewelry
    mu   sync.Mutex
}
 
func NewInMemoryJewelryRepo() JewelryRepository {
    return &InMemoryJewelryRepo{
        data: make(map[string]*domain.Jewelry),
    }
}
 
func (r *InMemoryJewelryRepo) Save(j *domain.Jewelry) {
    r.mu.Lock()
    defer r.mu.Unlock()
    r.data[j.ID] = j
}
 
func (r *InMemoryJewelryRepo) GetByID(id string) *domain.Jewelry {
    r.mu.Lock()
    defer r.mu.Unlock()
    return r.data[id]
}
Go 复制代码
/*
# 版权所有  2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:Lock/Mutex Pattern 互斥锁(Mutex)
# Author    : geovindu,Geovin Du 涂聚文.
# IDE       : goLang 2024.3.6 go 26.2
# os        : windows 10
# database  : mysql 9.0 sql server 2019, postgreSQL 17.0  Oracle 21c Neo4j
# Datetime  : 2026/5/11 22:02
# User      :  geovindu
# Product   : GoLand
# Project   : godesginpattern
# File      : jewelry_service.go
*/
package service
 
import (
    "godesginpattern/mutex/domain"
    "godesginpattern/mutex/repository"
)
 
type JewelryService struct {
    repo repository.JewelryRepository
}
 
func NewJewelryService(repo repository.JewelryRepository) *JewelryService {
    return &JewelryService{repo: repo}
}
 
// CreateJewelry 创建珠宝
func (s *JewelryService) CreateJewelry(id, name string, stock int) *domain.Jewelry {
    j := domain.NewJewelry(id, name, stock)
    s.repo.Save(j)
    return j
}
 
// SellJewelry 销售珠宝
func (s *JewelryService) SellJewelry(id string, num int) (bool, string) {
    j := s.repo.GetByID(id)
    if j == nil {
        return false, "珠宝不存在"
    }
    success, msg := j.Sell(num)
    s.repo.Save(j)
    return success, msg
}
 
// ReplenishJewelry 补货
func (s *JewelryService) ReplenishJewelry(id string, num int) (bool, string) {
    j := s.repo.GetByID(id)
    if j == nil {
        return false, "珠宝不存在"
    }
    success, msg := j.Replenish(num)
    s.repo.Save(j)
    return success, msg
}
 
// GetStock 查询库存
func (s *JewelryService) GetStock(id string) int {
    j := s.repo.GetByID(id)
    if j == nil {
        return 0
    }
    return j.GetStock()
}
Go 复制代码
/*
# 版权所有  2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:Lock/Mutex Pattern 互斥锁(Mutex)
# Author    : geovindu,Geovin Du 涂聚文.
# IDE       : goLang 2024.3.6 go 26.2
# os        : windows 10
# database  : mysql 9.0 sql server 2019, postgreSQL 17.0  Oracle 21c Neo4j
# Datetime  : 2026/5/11 22:03
# User      :  geovindu
# Product   : GoLand
# Project   : godesginpattern
# File      : jewelry_handler.go
*/
package handler
 
import (
    "fmt"
    "godesginpattern/mutex/service"
    "sync"
)
 
type JewelryHandler struct {
    svc *service.JewelryService
}
 
func NewJewelryHandler(svc *service.JewelryService) *JewelryHandler {
    return &JewelryHandler{svc: svc}
}
 
// RunConcurrentTasks 模拟企业级并发销售/补货
func (h *JewelryHandler) RunConcurrentTasks() {
    var wg sync.WaitGroup
 
    // 并发任务:5个协程同时操作
    wg.Add(5)
 
    go func() {
        defer wg.Done()
        _, msg := h.svc.SellJewelry("D001", 1)
        fmt.Printf("销售员A -> 销售1颗:%s | 库存:%d\n", msg, h.svc.GetStock("D001"))
    }()
 
    go func() {
        defer wg.Done()
        _, msg := h.svc.SellJewelry("D001", 1)
        fmt.Printf("销售员B -> 销售1颗:%s | 库存:%d\n", msg, h.svc.GetStock("D001"))
    }()
 
    go func() {
        defer wg.Done()
        _, msg := h.svc.SellJewelry("D001", 1)
        fmt.Printf("销售员C -> 销售1颗:%s | 库存:%d\n", msg, h.svc.GetStock("D001"))
    }()
 
    go func() {
        defer wg.Done()
        _, msg := h.svc.ReplenishJewelry("D001", 2)
        fmt.Printf("仓  库 -> 补货2颗:%s | 库存:%d\n", msg, h.svc.GetStock("D001"))
    }()
 
    go func() {
        defer wg.Done()
        _, msg := h.svc.SellJewelry("D001", 1)
        fmt.Printf("销售员D -> 销售1颗:%s | 库存:%d\n", msg, h.svc.GetStock("D001"))
    }()
 
    wg.Wait()
    fmt.Println("\n=== 所有并发任务执行完成 ===")
    fmt.Printf("最终库存:%d\n", h.svc.GetStock("D001"))
}

调用:

Go 复制代码
/*
# 版权所有  2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:Lock/Mutex Pattern 互斥锁(Mutex)
# Author    : geovindu,Geovin Du 涂聚文.
# IDE       : goLang 2024.3.6 go 26.2
# os        : windows 10
# database  : mysql 9.0 sql server 2019, postgreSQL 17.0  Oracle 21c Neo4j
# Datetime  : 2026/5/11 22:07
# User      :  geovindu
# Product   : GoLand
# Project   : godesginpattern
# File      : mutexbll.go
Mutex/
├── config/              # 配置定义
├──
│   ├── domain/          # 领域层(核心业务模型 + 锁封装)
│   │   └── jewelry.go   # 珠宝模型 + 互斥锁安全实现
│   ├── repository/      # 数据存储层(持久化)
│   │   └── jewelry_repo.go
│   ├── service/         # 业务逻辑层
│   │   └── jewelry_service.go
│   └── handler/         # 接口/入口层
│       └── jewelry_handler.go
├── cmd/                 # 启动入口
└── go.mod
*/
package bll
 
import (
    "godesginpattern/mutex/handler"
    "godesginpattern/mutex/repository"
    "godesginpattern/mutex/service"
)
 
func MutexMain() {
    // 初始化依赖(DI 依赖注入)
    repo := repository.NewInMemoryJewelryRepo()
    svc := service.NewJewelryService(repo)
    h := handler.NewJewelryHandler(svc)
 
    // 初始化钻石库存:1 颗
    svc.CreateJewelry("D001", "天然钻石", 1)
 
    // 执行并发业务
    h.RunConcurrentTasks()
}

输出:

相关推荐
ping某35 分钟前
专栏-null 和 undefined 到底是什么?
前端·javascript·后端
神奇小汤圆1 小时前
别再只会用ArrayList了!Java集合框架的性能天花板到底在哪?
后端
神奇小汤圆1 小时前
Dubbo 的 SPI 和 JDK 的 SPI 有什么区别?
后端
叫我少年1 小时前
C# 字符串基础
后端
道友可好2 小时前
从今天开始:你的第一个 Harness Engineering 实践
前端·人工智能·后端
其实是白羊2 小时前
CoderTools 1.5.3:让 AI 帮你看懂代码调用链路
后端·ai编程·vibecoding
妙码生花2 小时前
从 PHP 到 AI + Golang,程序员自救转型手记(二):目录结构、初始化 GIT、设计并开发配置系统
前端·后端·go
千寻girling2 小时前
一份不可多得的《微服务》教程
后端·面试·github
用户6362300571673 小时前
NestJS实战-文章专栏功能模块
后端
洛阳泰山3 小时前
从 0 到 1.6K Star:一个 Java 开源项目的增长复盘
人工智能·后端·开源