golang死锁

死锁概念

所谓死锁,是指两个或者两个以上线程在执行过程中,因争夺资源而产生互相等待的现象,若无外力作用,他们都将无法推进下去,此时,称系统处于死锁。

死锁产生条件

  1. 互斥条件:进程对所分配的资源进行排它性使用,即在一段时间内某资源只由一个进程占用。如果此时,还有其它的进程请求该资源,则请求者只能等待。
  2. 请求和保持条件:指进程已经保持至少一个资源,但又提出了新的资源请求,但是该资源正在被其他进程占有,此时,请求进程阻塞,但又对自己所获得的资源保持不放。
  3. 不剥夺条件:指进程已经获得的资源,在没有使用完之前,不能被剥夺,只能由该进程使用完后自己释放。
  4. 环路等待条件:指在发生死锁时,必然存在一个进程资源的环形链,即进程集合{p0、p1、p2、p3、…pn}中的p0正在等待一个p1占用的资源,pn正在等待一个p0占用的资源。

死锁解决方法

  1. 死锁预防:破坏导致死锁必要条件中的任何一个就可以预防死锁。例如,要求用户申请资源时一次性申请所需要的全部资源,这就破坏了保持和等待条件。将资源分层,得到上一层资源后,才能够申请下一层资源,它破坏了 环路等待条件。
  2. 死锁避免:避免是指进程在每次申请资源时判断这些操作是否安全。例如,使用银行家算法。
  3. 死锁检测:死锁预防和避免都是事前措施,而死锁的检测则是判断系统是否处于死锁状态,如果是,则执行死锁解除策略。
  4. 死锁解除:与死锁检测结合使用。它使用的方式就是剥夺。即将某进程所拥有的资源强行收回,分配给其他的进程。

例子

package main

import (
	"fmt"
	"strings"
)

// 做整个功能模块的封装
type LogProcess struct {
	path       string // 文件的路径
	influxDBsn string // 存储数据库的信息

	rc chan string // 从读取模块到
	wc chan string
}

// 用引用去接受  不会做拷贝的操作  并且能够改变自己的属性
func (l *LogProcess) ReadFromFile() {
	// 读取模块
	line := "message"
	l.rc <- line
}

func (l *LogProcess) Process() {
	// 解析模块
	data := <-l.rc
	l.wc <- strings.ToUpper(data)

}

func (l *LogProcess) WriteToInfluxDB() {
	// 写入模块
	fmt.Println(<-l.wc)
}

func main() {
	lp := &LogProcess{
		path:       "/tmp/access.log",
		influxDBsn: "username&password",
		wc:         make(chan string),
		rc:         make(chan string),
	}

	// 三个模块独立的并发执行
	// 怎么实现三个模块之间的通信 -> 用chan
	go lp.ReadFromFile()
	go lp.Process()
	go lp.WriteToInfluxDB()

	select {}

}

输出结果

MESSAGE fatal error: all goroutines are asleep - deadlock!

分析

从结果上看程序正常执行完成之后,产生了死锁,报错信息也很明显,所有的goroutines都在睡眠状态,都在等待数据的产生,所以出现死锁。

参考:https://blog.csdn.net/baidu_33604078/article/details/78156152

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值