@wubbacom
PHP developer

Deadlock — возникает блокировка, из-за чего она происходит?

Ребят привет! я новичок в Go. Сижу, уже 4 день и не могу понять, что я делаю не так. Задача такая: во вход передаются данные, хешируются и передаются дальше в функцию MultiHash, дальше MultiHash должна их прочесть еще раз захешировать и передать следующей функции (следующую функцию еще пока не реализовал). Попытка реализовать pipeline, в функции MultiHash пытаюсь прочесть данные из канала, но у меня возникает deadlock. На какой этапе я допускаю ошибку?
Я вижу на каких строчках возникают проблемы, но не могу понять в каком порядке их разбирать и как это все сделать рабочим

signer.go
package main

import (
	"fmt"
	"os"
	"sync"
)

// сюда писать код

func SingleHash(done chan interface{}, in []string) {

	defer close(done)

	fmt.Println(in)
	wg := &sync.WaitGroup{}
	mu := &sync.Mutex{}

	for _, i := range in {
		wg.Add(1)
		go workerSingleHash(wg, mu, i, done)
	}

	wg.Wait()
	fmt.Println("end singlehash")

}

func workerSingleHash(wg *sync.WaitGroup, mu *sync.Mutex, in string, done chan interface{}) {
	fmt.Println(in)
	defer wg.Done()

	crc32Chan := make(chan string)

	mu.Lock()
	md5Data := DataSignerMd5(in)
	mu.Unlock()

	go asyncCrc32Signer(in, crc32Chan)

	crc32Data := <-crc32Chan
	crc32Md5Data := DataSignerCrc32(md5Data)

	done <- crc32Data + "~" + crc32Md5Data

}

func asyncCrc32Signer(data string, out chan string) {
	defer close(out)

	out <- DataSignerCrc32(data)
}

func main() {
	done := make(chan interface{})
	
	in := os.Args

	SingleHash(done, in[1:])

	go func(done chan interface{}) {
		for v := range done {
			fmt.Println(v)
		}
	}(done)
}


Это функции которые хешируют, DataSignerCrc32 нельзя использовать сраза одну за одной, так как случается перегрев, их нужно распараллелить. этот файл не мой - это условие и я с ним справился, но проблема не в этом, просто выкладываю, что б могли понять что это за функции
common.go
package main

import (
	"crypto/md5"
	"fmt"
	"hash/crc32"
	"strconv"
	"sync/atomic"
	"time"
)

type job func(in, out chan interface{})

const (
	MaxInputDataLen = 100
)

var (
	dataSignerOverheat uint32 = 0
	DataSignerSalt            = ""
)

var OverheatLock = func() {
	for {
		if swapped := atomic.CompareAndSwapUint32(&dataSignerOverheat, 0, 1); !swapped {
			fmt.Println("OverheatLock happend")
			time.Sleep(time.Second)
		} else {
			break
		}
	}
}

var OverheatUnlock = func() {
	for {
		if swapped := atomic.CompareAndSwapUint32(&dataSignerOverheat, 1, 0); !swapped {
			fmt.Println("OverheatUnlock happend")
			time.Sleep(time.Second)
		} else {
			break
		}
	}
}

var DataSignerMd5 = func(data string) string {
	OverheatLock()
	defer OverheatUnlock()
	data += DataSignerSalt
	dataHash := fmt.Sprintf("%x", md5.Sum([]byte(data)))
	time.Sleep(10 * time.Millisecond)
	return dataHash
}

var DataSignerCrc32 = func(data string) string {
	data += DataSignerSalt
	crcH := crc32.ChecksumIEEE([]byte(data))
	dataHash := strconv.FormatUint(uint64(crcH), 10)
	time.Sleep(time.Second)
	return dataHash
}


Вот такая простыня
fatal error: all goroutines are asleep - deadlock!

goroutine 1 [semacquire]:
sync.runtime_Semacquire(0xc00001a0f8)
        C:/Program Files/Go/src/runtime/sema.go:56 +0x49
sync.(*WaitGroup).Wait(0xc00001a0f0)
        C:/Program Files/Go/src/sync/waitgroup.go:130 +0x6b
main.SingleHash(0xc000018180, 0xc00002c090, 0x3, 0x3)
        C:/Users/engis/OneDrive/Рабочий стол/Go-learn-master/Go-learn-master/hw2_signer/signer.go:24 +0x1cc
main.main()
        C:/Users/engis/OneDrive/Рабочий стол/Go-learn-master/Go-learn-master/hw2_signer/signer.go:68 +0xc5

goroutine 6 [chan send]:
main.workerSingleHash(0xc00001a0f0, 0xc00001a0c8, 0xb36b68, 0x1, 0xc000018180)
        C:/Users/engis/OneDrive/Рабочий стол/Go-learn-master/Go-learn-master/hw2_signer/signer.go:45 +0x2b7
created by main.SingleHash
        C:/Users/engis/OneDrive/Рабочий стол/Go-learn-master/Go-learn-master/hw2_signer/signer.go:21 +0x1a5

goroutine 7 [chan send]:
main.workerSingleHash(0xc00001a0f0, 0xc00001a0c8, 0xb36b78, 0x1, 0xc000018180)
        C:/Users/engis/OneDrive/Рабочий стол/Go-learn-master/Go-learn-master/hw2_signer/signer.go:45 +0x2b7
created by main.SingleHash
        C:/Users/engis/OneDrive/Рабочий стол/Go-learn-master/Go-learn-master/hw2_signer/signer.go:21 +0x1a5

goroutine 8 [chan send]:
main.workerSingleHash(0xc00001a0f0, 0xc00001a0c8, 0xb36b88, 0x1, 0xc000018180)
        C:/Users/engis/OneDrive/Рабочий стол/Go-learn-master/Go-learn-master/hw2_signer/signer.go:45 +0x2b7
created by main.SingleHash
        C:/Users/engis/OneDrive/Рабочий стол/Go-learn-master/Go-learn-master/hw2_signer/signer.go:21 +0x1a5
exit status 2
  • Вопрос задан
  • 761 просмотр
Решения вопроса 1
Вижу такую проблему:
  1. Вы создаете небуферизированный канал done.
  2. Функции, пытающиеся записать в канал done блокируются, пока канал не будет прочитан.


Предлагаю такое исправление - в функции main запускать SingleHash(done, in[1:]) как горутину, чтобы не блокировать main и перейти к ожиданию ответа из канала done. И в данном случае go func(done chan interface{}) нужно будет выполнить синхронно, а не горутиной.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы