热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Golang同步:条件变量和锁组合使用

条件变量的作用并不是保证在同一时刻仅有一个线程访问某一个共享数据,而是在对应的共享数据的状态发生变化时,通知其他因此而被阻塞的线程。条件变量与互斥量组合使用互

条件变量的作用并不是保证在同一时刻仅有一个线程访问某一个共享数据,而是在对应的共享数据的状态发生变化时,通知其他因此而被阻塞的线程。

  • 条件变量与互斥量组合使用
  • 互斥量为共享数据的访问提供互斥支持
  • 条件变量就状态的变化向相关线程发出通知

三种操作方法
  • 等待通知: wait
    • 阻塞当前线程,直到收到该条件变量发来的通知
  • 单发通知: signal
    • 让该条件变量向至少一个正在等待它的通知的线程发送通知,表示共享数据的状态已经改变。
  • 广播通知: broadcast
    • 让条件变量给正在等待它的通知的所有线程都发送通知。

声明

func NewCond(l Locker) *Cond

示例

改造上一节的锁使用代码

Golang同步:锁的使用案例详解
传送门:http://blog.csdn.net/liuxinmingcode/article/details/50044327

Read()方法改造如下:

func (df *myDataFile) Read() (rsn int64, d Data, err error){
    // 读取并更新读偏移量
    var offset int64
    // 读互斥锁定
    df.rmutex.Lock()
    offset = df.roffset
    // 更改偏移量, 当前偏移量+数据块长度
    df.roffset += int64(df.dataLen)
    // 读互斥解锁
    df.rmutex.Unlock()

    //读取一个数据块,最后读取的数据块序列号
    rsn = offset / int64(df.dataLen)
    bytes := make([]byte, df.dataLen)
    //读写锁:读锁定
    df.fmutex.RLock()
    defer df.fmutex.RUnlock()

    for {
        _, err = df.f.ReadAt(bytes, offset)
        if err != nil {
            if err == io.EOF {
                //暂时放弃fmutex的 读锁,并等待通知的到来
                df.rcond.Wait()
                continue
            }
        }
        return
    }
    d = bytes
    return
}

Write()方法改造如下:

func (df *myDataFile) Write(d Data) (wsn int64, err error){
    //读取并更新写的偏移量
    var offset int64
    df.wmutex.Lock()
    offset = df.woffset
    df.woffset += int64(df.dataLen)
    df.wmutex.Unlock()

    //写入一个数据块,最后写入数据块的序号
    wsn = offset / int64(df.dataLen)
    var bytes []byte
    if len(d) > int(df.dataLen){
        bytes = d[0:df.dataLen]
    }else{
        bytes = d
    }
    df.fmutex.Lock()
    defer df.fmutex.Unlock()
    _, err = df.f.Write(bytes)
    //发送通知
    df.rcond.Signal()
    return
}

因为一个数据块只能有一个读操作读取,因此我们使用条件变量Signal方法通知某一个为此等待的Wait方法,唤醒一个相关的Goroutine。

还有一件事不能忘记,初始化rcond字段

func NewDataFile(path string, dataLen uint32) (DataFile, error){
    //f, err := os.OpenFile(path, os.O_APPEND|os.O_RDWR|os.O_CREATE, 0666)
    f,err := os.Create(path)
    if err != nil {
        fmt.Println("Fail to find", f, "cServer start Failed")
        return nil, err
    }

    if dataLen == 0 {
        return nil, errors.New("Invalid data length!")
    }

    df := &myDataFile{
        f : f,
        dataLen:dataLen,
    }
    //创建一个可用的条件变量(初始化),返回一个*sync.Cond类型的结果值,我们就可以调用该值拥有的三个方法Wait,Signal,Broadcast
    df.rcOnd= sync.NewCond(df.fmutex.RLocker())
    return df, nil
}

源代码:
https://github.com/lxmgo/learngo


推荐阅读
  • 按照之前我对map的理解,map中的数据应该是有序二叉树的存储顺序,正常的遍历也应该是有序的遍历和输出,但实际试了一下,却发现并非如此,网上查了下,发现从Go1开始,遍历的起始节点就是随机了,当然随机 ... [详细]
  • 本文介绍了一种求解最小权匹配问题的方法,使用了拆点和KM算法。通过将机器拆成多个点,表示加工的顺序,然后使用KM算法求解最小权匹配,得到最优解。文章给出了具体的代码实现,并提供了一篇题解作为参考。 ... [详细]
  • golang 解析磁力链为 torrent 相关的信息
    其实通过http请求已经获得了种子的信息了,但是传播存储种子好像是违法的,所以就存储些描述信息吧。之前python跑的太慢了。这个go并发不知道写的有没有问题?!packag ... [详细]
  • 目录在Go语言项目中使用Zap日志库介绍默认的GoLogger日志库实现GoLogger设置Logger使用LoggerLogger的运行GoLogger的优势和劣势优势劣势Ube ... [详细]
  • 在Android开发中,使用Picasso库可以实现对网络图片的等比例缩放。本文介绍了使用Picasso库进行图片缩放的方法,并提供了具体的代码实现。通过获取图片的宽高,计算目标宽度和高度,并创建新图实现等比例缩放。 ... [详细]
  • 本文介绍了数据库的存储结构及其重要性,强调了关系数据库范例中将逻辑存储与物理存储分开的必要性。通过逻辑结构和物理结构的分离,可以实现对物理存储的重新组织和数据库的迁移,而应用程序不会察觉到任何更改。文章还展示了Oracle数据库的逻辑结构和物理结构,并介绍了表空间的概念和作用。 ... [详细]
  • 本文主要解析了Open judge C16H问题中涉及到的Magical Balls的快速幂和逆元算法,并给出了问题的解析和解决方法。详细介绍了问题的背景和规则,并给出了相应的算法解析和实现步骤。通过本文的解析,读者可以更好地理解和解决Open judge C16H问题中的Magical Balls部分。 ... [详细]
  • CF:3D City Model(小思维)问题解析和代码实现
    本文通过解析CF:3D City Model问题,介绍了问题的背景和要求,并给出了相应的代码实现。该问题涉及到在一个矩形的网格上建造城市的情景,每个网格单元可以作为建筑的基础,建筑由多个立方体叠加而成。文章详细讲解了问题的解决思路,并给出了相应的代码实现供读者参考。 ... [详细]
  • 纠正网上的错误:自定义一个类叫java.lang.System/String的方法
    本文纠正了网上关于自定义一个类叫java.lang.System/String的错误答案,并详细解释了为什么这种方法是错误的。作者指出,虽然双亲委托机制确实可以阻止自定义的System类被加载,但通过自定义一个特殊的类加载器,可以绕过双亲委托机制,达到自定义System类的目的。作者呼吁读者对网上的内容持怀疑态度,并带着问题来阅读文章。 ... [详细]
  • 本文分析了Wince程序内存和存储内存的分布及作用。Wince内存包括系统内存、对象存储和程序内存,其中系统内存占用了一部分SDRAM,而剩下的30M为程序内存和存储内存。对象存储是嵌入式wince操作系统中的一个新概念,常用于消费电子设备中。此外,文章还介绍了主电源和后备电池在操作系统中的作用。 ... [详细]
  • 看到平台银行对接方案写的demo确实还不错记个笔记互相学习学习packageapiimport(cryptotlsnetnethttpstringssynct ... [详细]
  • 集成第三方库,自检测读取配置文件。文件读取,结构体定义,接口实现,错误返回,库解析,适合新同学练手。思路文件读取获取字节流文件类型分析,确定解析api集成第三方解析api管理器定义 ... [详细]
  • 本文讨论了使用差分约束系统求解House Man跳跃问题的思路与方法。给定一组不同高度,要求从最低点跳跃到最高点,每次跳跃的距离不超过D,并且不能改变给定的顺序。通过建立差分约束系统,将问题转化为图的建立和查询距离的问题。文章详细介绍了建立约束条件的方法,并使用SPFA算法判环并输出结果。同时还讨论了建边方向和跳跃顺序的关系。 ... [详细]
  • 本文介绍了Swing组件的用法,重点讲解了图标接口的定义和创建方法。图标接口用来将图标与各种组件相关联,可以是简单的绘画或使用磁盘上的GIF格式图像。文章详细介绍了图标接口的属性和绘制方法,并给出了一个菱形图标的实现示例。该示例可以配置图标的尺寸、颜色和填充状态。 ... [详细]
  • ***byte(字节)根据长度转成kb(千字节)和mb(兆字节)**parambytes*return*publicstaticStringbytes2kb(longbytes){ ... [详细]
author-avatar
karen_8009
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有