You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Golang中创建命名互斥锁?复刻Windows CreateMutex逻辑

在Go中实现Windows命名互斥锁

Go标准库的sync.Mutex仅支持进程内部的同步,无法实现Windows API中CreateMutex那样的跨进程命名互斥锁。要实现跨进程同步,必须直接调用Windows系统API,以下是两种可行方案:

方案一:使用golang.org/x/sys/windows包(推荐)

这是Go官方提供的系统调用扩展包,使用更安全、便捷。先执行安装命令:

go get golang.org/x/sys/windows

示例代码:

package main

import (
    "golang.org/x/sys/windows"
    "log"
)

func main() {
    // 将互斥锁名称转换为Windows要求的UTF-16指针
    mutexName, err := windows.UTF16PtrFromString("NameOfMutexObject")
    if err != nil {
        log.Fatal(err)
    }

    // 对应Windows API的CreateMutex调用
    // 参数:安全描述符(nil对应NULL)、初始拥有者(false对应FALSE)、互斥锁名称
    hMutex, err := windows.CreateMutex(nil, false, mutexName)
    if err != nil {
        log.Fatalf("创建互斥锁失败: %v", err)
    }
    // 确保程序退出时释放句柄
    defer windows.CloseHandle(hMutex)

    // 等待获取互斥锁,INFINITE表示无限等待
    waitResult, err := windows.WaitForSingleObject(hMutex, windows.INFINITE)
    if err != nil {
        log.Fatalf("等待互斥锁失败: %v", err)
    }

    switch waitResult {
    case windows.WAIT_OBJECT_0:
        log.Println("成功获取互斥锁")
        // 在此执行需要跨进程同步的操作
        // ...

        // 操作完成后释放互斥锁
        if err := windows.ReleaseMutex(hMutex); err != nil {
            log.Fatalf("释放互斥锁失败: %v", err)
        }
    case windows.WAIT_ABANDONED:
        log.Println("获取到被遗弃的互斥锁(之前持有锁的进程异常退出)")
    }
}

方案二:直接调用kernel32.dll(不推荐,依赖syscall已弃用)

如果不想引入第三方包,可以直接通过syscall调用Windows原生API,但syscall在Go 1.16后已被标记为弃用,仅作兼容参考:

package main

import (
    "log"
    "syscall"
    "unsafe"
)

var (
    kernel32             = syscall.NewLazyDLL("kernel32.dll")
    createMutexW         = kernel32.NewProc("CreateMutexW")
    waitForSingleObject  = kernel32.NewProc("WaitForSingleObject")
    releaseMutex         = kernel32.NewProc("ReleaseMutex")
    closeHandle          = kernel32.NewProc("CloseHandle")
)

func main() {
    mutexName, err := syscall.UTF16PtrFromString("NameOfMutexObject")
    if err != nil {
        log.Fatal(err)
    }

    // 调用CreateMutexW
    hMutex, _, err := createMutexW.Call(0, 0, uintptr(unsafe.Pointer(mutexName)))
    if hMutex == 0 {
        log.Fatalf("创建互斥锁失败: %v", err)
    }
    defer func() {
        _, _, _ = closeHandle.Call(hMutex)
    }()

    // 等待获取锁
    result, _, err := waitForSingleObject.Call(hMutex, uintptr(syscall.INFINITE))
    switch result {
    case uintptr(syscall.WAIT_OBJECT_0):
        log.Println("成功获取互斥锁")
        // 执行同步操作
        // ...

        // 释放锁
        _, _, err := releaseMutex.Call(hMutex)
        if err != syscall.Errno(0) {
            log.Fatalf("释放互斥锁失败: %v", err)
        }
    case uintptr(syscall.WAIT_ABANDONED):
        log.Println("获取到被遗弃的互斥锁")
    default:
        log.Fatalf("等待锁失败: %v", err)
    }
}

关键说明

  • 命名互斥锁是系统级资源,不同进程使用相同名称即可共享该锁
  • 必须在使用完成后调用CloseHandle释放句柄,避免资源泄漏
  • 如果创建时将bInitialOwner设为true,当前进程会直接持有锁,需手动调用ReleaseMutex释放

内容的提问来源于stack exchange,提问作者stubble jumper

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 16:30:46