zoukankan      html  css  js  c++  java
  • 周记7

    记一次Go slice在并发中不安全的坑

    当时的软件结构是,系统启动后会启动n个 goroutine, 然后所有的goroutine等待Task的到来,并发的处理多个task。

    在task到来的时候,进行相关参数的拼接(故障就出在这),然后调用shell 执行命令

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    // 获取参数与参数拼接代码
    params = rsync.params

    params = buildParms(params, src, dst)

    exec(params)


    func buildParams(params, src, dst) []string {
    params = append(...)
    return params
    }

    代码执行之后,当并发量比较大的时候,会发现 build之后的params 的最后几个字符串会异常

    知道是并发slice线程安全的问题,但是解决办法,百思不得其解

    后来问题聚焦于append ,google 证实append的确不是一个线程安全的函数,并发执行直接的话,会导致data race

    在go playground 中 :发现了一点起色,就是

    buildParams 函数 每次新建一个新的 slice 然后 返回新的 slice

    结果发现 现象的确少了很多,但是还是有

    后来发现,只要 在调用上层 也新建slice 就可以完全规避这个问题。

    也就是不要在并发的时候 公用一个 slice 一定要每次操作都进行新建。

    1
    2
    3
    4
    5
    6
    7
    8
    9

    // 改进之后的 拼装参数方法
    func buildParams(params []string, src string, dst string) []string {
    s := make([]string, 0)
    s = append(s, params...)
    s = append(s, src)
    s = append(s, dst)
    return s
    }

    Go

    goland vendor 不识别

    goland不会识别 vendor 文件夹下的相关dep

    所以 可以使用 文件夹下带 src目录,然后添加到 project PATH 就可以正常的代码提示

    Go 跨平台编译

    用于减少开发成本 build 了之后 直接 rsync上去

    CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o

    Go 不能 在exec shell的时候直接 cd

    cmd.Dir = “/“

    map 非线程安全 增删改查需要 加锁

    信号量 控制并发数量

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    package utils

    import "sync"

    type Semaphore struct {
    maxNum int
    Threads chan int
    Wg sync.WaitGroup
    }

    func NewSemaphore (maxNum int) *Semaphore {
    var sem = new(Semaphore)
    sem.maxNum = maxNum
    sem.Threads = make(chan int, maxNum)
    return sem
    }

    func (sem *Semaphore) P() {
    sem.Threads <- 1
    sem.Wg.Add(1)
    }

    func (sem *Semaphore) V() {
    sem.Wg.Done()
    <-sem.Threads
    }

    func (sem *Semaphore) Wait() {
    sem.Wg.Wait()
    }

    func (sem *Semaphore) Discard() {
    sem.Threads = make(chan int, sem.maxNum)
    }

    PHP

    脚本中存在死循环的调用

    有一个类 里面有各种方法 外加一个 死循环 的 check方法

    在其他方法调用这个类的其他方法的时候 Class::otherMethod();

    fpm 出现了504

    百思不得其解

    phpunit测试发现,在调用static方法的时候,竟然连 check()方法一起执行了你敢信?

    所以 执行和类 需要分开

  • 相关阅读:
    Oracle数据导入导出脚本示例 Yang
    Golang基本数据类型 Yang
    SQL数据库使用游标示例 Yang
    Oracle数据库使用游标简单示例 Yang
    Oracle存储过程简单示例 Yang
    利用Excel内置功能快速导出数据到Excel
    程序间相互通讯问题的解决
    C#动态方法调用
    修改的一个导出DataSet到xls的单元
    Excel To SqlServer
  • 原文地址:https://www.cnblogs.com/xiaoerli520/p/9624345.html
Copyright © 2011-2022 走看看