go语言--竞争、原子函数、互斥锁

一、go语言竞争状态、原子函数、互斥锁

下面代码例子是展示并发下公共数据操作,通过原子函数和互斥锁怎么解决。

package main

import (
    "sync"
    "runtime"
    "fmt"
    "sync/atomic"
)

var(
    // counter是所有goroutine都要增加的变量
    counter int64
    // wg用来等待程序的结束
    wg sync.WaitGroup
    // mutex 用来定义一段代码临界区
    mutex sync.Mutex
)

func main() {
    // 计数加2,表示要等待两个goroutine
    wg.Add(2)
    // 创建两个goroutine
    go incCounter(1)
    go incCounter(2)
    // 等待goroutine结束
    wg.Wait()
    fmt.Println("Final Counter:", counter)
}

// incCounter增加包里counter变量的值
func incCounter(id int) {
    // 延时调用,在函数退出时调用Done来通知main函数工作已经完成
    defer wg.Done()

    for count := 0; count < 2; count++ {
        // 捕获counter的值
        value := counter
        // 当前goroutine从线程退出,并放回到队列
        runtime.Gosched()
        // 增加本地value变量的值
        value++
        // 将该值保存回counter
        counter = value
    }
}
// incCounter增加包里counter变量的值
func incCounter1(id int) {
    defer wg.Done()

    for count := 0; count < 2; count++ {
        // 安全的对counter加1
        atomic.AddInt64(&counter, 1)
        // 当前goroutine从线程退出,并放回到队列
        runtime.Gosched()
    }
}

// incCounter增加包里counter变量的值
func incCounter2(id int) {
    // 延时调用,在函数退出时调用Done来通知main函数工作已经完成
    defer wg.Done()

    for count := 0; count < 2; count++ {
        // 同一时刻只允许一个goroutine进入这个临界区
        mutex.Lock()
        {
            // 捕获counter的值
            value := counter
            // 当前goroutine从线程退出,并放回到队列
            runtime.Gosched()
            // 增加本地value变量的值
            value++
            // 将该值保存回counter
            counter = value
        }
        // 释放锁,允许其他正在等待的goroutine进入临界区
        mutex.Unlock()
    }
}
  • 下面图片是竞争状态下的数据交互模型

原文地址:https://www.cnblogs.com/wudiffs/p/11576683.html

时间: 2024-08-28 12:54:05

go语言--竞争、原子函数、互斥锁的相关文章

原子属性与非原子属性,互斥锁与自旋锁介绍

nonatomic 非原子属性 非线程安全,适合内存小的移动设备(手机,平板...) atomic 原子属性(线程安全,但需要消耗大量资源)针对多线程设计的,为默认值,保证同一时间只有一个线程能够写入;本身就是一把自旋锁;单写多读,单个线程写入,多个线程读取 注意:当重写属性的get与set方法时需要在@implementation后添加:@synthesiae 属性名 = _属性名; 互斥锁与自旋锁对比 互斥锁:如果发现其他线程正在执行锁定代码,线程会进入休眠(就绪状态),等其他线程时间到打开

使用自旋锁和互斥锁实现的原子属性的性能对比

代码: #import "ViewController.h" extern uint64_t dispatch_benchmark(size_t count, void (^block)(void)); @interface ViewController () // 原子属性 - 互斥锁实现 @property (strong, nonatomic) NSObject *obj1; // 原子属性 - 自旋锁实现 @property (strong, atomic) NSObject

ReactiveSwift源码解析(十一) Atomic的代码实现以及其中的Defer延迟、Posix互斥锁、递归锁

本篇博客我们来聊一下ReactiveSwift中的原子性操作,在此内容上我们简单的聊一下Posix互斥锁以及递归锁的概念以及使用场景.然后再聊一下Atomic的代码实现.Atomic主要负责多线程下的原子操作,负责共享资源的同步一致性.而在Atomic中就是使用到了Posix互斥锁和递归锁.在聊上述内容之前,我们先来回顾一下Swift语言中延迟执行defer的使用方式,在之前Swift编程的相关博客中也涉及到了defer的使用方式.defer因为Atomic使用到了延迟操作,所以下方我们再做一个

互斥锁- pthread_mutex

一. 什么是互斥锁 计算机中,当多个进程或者线程共享一个临界区(例如:共享内存空间或者全局变量),如果仅对该临界区读取,不进行内容修改,即使同时多次读取都是没有问题的. 但是,当我们需要修改临界区内的内容时,我们就必须面对一个情况:同时有多个操作对临界区的内容进行修改,在操作完后,保留的是那一次操作的结果?为了解决这个 问题,可以规定对临界区的修改操作,同时最多只能有一个来修改.程序中实现的方法之一就是互斥锁. 互斥锁,具有三个特点: (i)原子性:把一个互斥锁定义为一个原子操作,这意味着操作系

Go语言,用原子函数atomic避免资源竞争

下一步应该是互斥锁了. package main import ( "fmt" "runtime" "sync" "sync/atomic" ) var ( counter int64 wg sync.WaitGroup ) func main() { wg.Add(2) fmt.Println("Create Goroutines") go incCounter(1) go incCounter(2) f

Linux 同步方法剖析--内核原子,自旋锁和互斥锁

在学习 Linux® 的过程中,您也许接触过并发(concurrency).临界段(critical section)和锁定,但是如何在内核中使用这些概念呢?本文讨论了 2.6 版内核中可用的锁定机制,包括原子运算符(atomic operator).自旋锁(spinlock).读/写锁(reader/writer lock)和内核信号量(kernel semaphore). 本文还探讨了每种机制最适合应用到哪些地方,以构建安全高效的内核代码. 本文讨论了 Linux 内核中可用的大量同步或锁定

互斥锁 pthread_mutex_init()函数

Linux下为了多线程同步,通常用到锁的概念.posix下抽象了一个锁类型的结构:ptread_mutex_t.通过对该结构的操作,来判断资源是否可以访问.顾名思义,加锁(lock)后,别人就无法打开,只有当锁没有关闭(unlock)的时候才能访问资源. 即对象互斥锁的概念,来保证共享数据操作的完整性.每个对象都对应于一个可称为" 互斥锁" 的标记,这个标记用来保证在任一时刻,只能有一个线程访问该对象. 使用互斥锁(互斥)可以使线程按顺序执行.通常,互斥锁通过确保一次只有一个线程执行代

037_go语言中的互斥锁

代码演示: package main import ( "fmt" "math/rand" "runtime" "sync" "sync/atomic" "time" ) func main() { var state = make(map[int]int) var mutex = &sync.Mutex{} var ops int64 = 0 for r := 0; r <

python-多线程同步中创建互斥锁解决资源竞争的问题

import threadingimport time # 定义一个全局变量g_num = 0 def test1(num): global g_num for i in range(num): g_num += 1 print('-------in test1 g_num={}'.format(g_num)) def test2(num): global g_num for i in range(num): g_num += 1 print('-------in test1 g_num={}'