首页 > 编程语言 >极客时间--golang并发编程实战课--Mutex学习总结

极客时间--golang并发编程实战课--Mutex学习总结

时间:2023-06-04 12:55:39浏览次数:53  
标签:wg 极客 -- sync value golang ++ 临界 Mutex

互斥锁的实现机制

  互斥锁是并发控制的一个手段,是为了避免竞争而建立的一种并发控制机制。在并发编程中,如果程序中的一部分会被并发访问或修改,那么,为了避免并发访问导致的意想不到的结果,这部分程序需要被保护起来,这部分被保护起来的程序,就叫做临界区。可以说,临界区就是一个被共享的资源,或者说是一个整体的一组共享资源,比如对数据库的访问、对某一个共享数据结构的操作、对一个 I/O 设备的使用、对一个连接池中的连接的调用,等等。如果很多线程同步访问临界区,就会造成访问或操作错误,这当然不是我们希望看到的结果。所以,我们可以使用互斥锁,限定临界区只能同时由一个线程持有。当临界区由一个线程持有的时候,其它线程如果想进入这个临界区,就会返回失败,或者是等待。直到持有的线程退出临界区,这些等待线程中的某一个才有机会接着持有这个临界区。

Mutex的使用方法

数据结构:

Mutex实现了如下接口,

type Locker interface{
    Lock()
    UnLock()
}

Mutex提供了如下两个方法:进入临界区调用Lock(),退出临界区调用UnLock()

func (m *Mutex)Lock()
func (m *Mutex)UnLock()

当一个 goroutine 通过调用 Lock 方法获得了这个锁的拥有权后,其它请求锁的goroutine 就会阻塞在 Lock 方法的调用上,直到锁被释放并且自己获取到了这个锁的拥有权。

下面来看一段代码:

package main

import (
	"fmt"
	"sync"
)

var wg sync.WaitGroup
var lock sync.Mutex

type Mutext struct {
}

func main() {
	var value = 0
	wg.Add(10)
	for i := 0; i < 10; i++ {
		go func() {
			defer wg.Done()
			for j := 0; j < 1000; j++ {
				//lock.Lock()
				value++
				//lock.Unlock()
			}
		}()
	}
	wg.Wait()
	fmt.Println(value)
}

上述代码中,value++就是一个临界区的概念,如果没有对其加锁,那么最终输出的value结果不是我们希望得到的,只有当对其加锁/解锁之后,才能保证在每次执行该操作只有一个goroutine(协程)。

同样,我们可以基于golang中结构体去优化上部分代码,谈不上优化,就是使用结构体去封装一个线程安全的计数器,可以将sync.Mutex作为一个字段,嵌入到结构体中去

package main

import (
	"fmt"
	"sync"
)

var wg sync.WaitGroup
var lock sync.Mutex

type Value struct {
	mu    sync.Mutex
	value int
}

func main() {
	var value Value
	wg.Add(10)
	for i := 0; i < 10; i++ {
		go func() {
			defer wg.Done()
			for j := 0; j < 1000; j++ {
				value.mu.Lock()
				value.value++
				value.mu.Unlock()
			}
		}()
	}
	wg.Wait()
	fmt.Println(value.value)
}

 

标签:wg,极客,--,sync,value,golang,++,临界,Mutex
From: https://www.cnblogs.com/99kol/p/17455540.html

相关文章

  • 网安--用户权限管理
    用户组group组ID--GID1.root用户组:GID=0(反之也成立)2.程序用户组(系统用户组):1-9993.普通用户组:1000-65535相关操作:cat/etc/group                       查看所有用户useradd-g组名用户                  在组中添加用户use......
  • kubernetes 部署SonarQube
    1.PostgreSQL参考博客:https://hanggi.me/post/kubernetes/k8s-postgresql1.1.配置PostgreSQL的ConfigMapcat>postgres-configmap.yaml<<EOFapiVersion:v1kind:ConfigMapmetadata:name:postgres-confignamespace:kube-opslabels:app:postgresd......
  • Side by Side 1, Third Edition [Longman] + AUDIO
    SidebySide1,ThirdEdition[Longman]+AUDIOLevel:BeginnerA1Описание:SidebySide,ThirdEdition,byStevenJ.MolinskyandBillBliss,isadynamic,all-skillsprogramthatintegratesconversationpractice,reading,writing,andlistening—al......
  • 深入学习ThreadLocal
    1、用来干吗的?用于线程在任意的地方去共享数据,而不被其他线程所干扰,2、原理是什么因为每个线程维护一份ThreadLocalMap,使用threadlocal.set(obj)方法是存放在map里面的Entry<<WeekReference>ThreadLocal,Value>数组里3、实际案例,比如写了util类,但是SimplateDateFormate是线程......
  • 1
    //==UserScript==//@name        sketchfab//@version     2.1//@description downloadsketchfabmodels//@author      great//@match       *://*.sketchfab.com/*//@require     https://lf9-cdn-tos.bytecdntp.com/cdn/e......
  • ansible实战-2023
    环境信息:cat/etc/ansible/hosts[webserver]192.168.31.18ansible_ssh_user=rootansible_ssh_pass=123456http_port=815testvar=31.18mysql_port=3309[dbserver]192.168.31.19ansible_ssh_user=rootansible_ssh_pass=123456http_port=816testvar=31.19mysql_port=3310......
  • 调整word序号的格式
     点击定义新编号格式是设置左顶格或右顶格。 右键字体设置大小......
  • 自动拉取 Gitlab 的所有仓库
    自动拉取Gitlab的所有仓库每次重装电脑或者一个新的gitlab项目需要拉取,就需要拉仓库思路获取到自己有权限的所有分组获取到分组下的仓库列表自动创建二级目录并使用sshclone仓库使用gitlab提供的rest接口api/v4/groups//有权限的分组curl--header"PRIVAT......
  • vimrc
    vsvimrcsetenc=utf-8setfencs=utf-8,gbk,big5,cp936,gb18030,gb2312,utf-16setfenc=utf-8setshortmess=atI"禁止bellsetbelloff=allsetvisualbellsett_vb=letmapleader="\<Space>"inoremapjj<ESC>"----------------......
  • MAC为usr/local/bin添加新脚本
    方法一创建脚本文件,删除后缀名将脚本文件添加到/usr/local/bin/目录下使用sudochmod777/usr/local/bin/yourscriptname修改访问权限此时可以看见,文件显示为Unix可执行文件重启控制台即可使用方法二创建脚本文件,不需删除后缀使用sudoIn-s/yourpath/......