Alla ricerca dello stallo


18

Alla ricerca dello stallo

Quando si programma un'applicazione multithreading, è necessario prestare molta attenzione per evitare il deadlock dei vari thread quando si accede alle risorse condivise. Un deadlock si verifica quando un thread tenta di accedere a una risorsa bloccata in un altro thread nello stesso momento in cui l'altro thread sta tentando di accedere a una risorsa bloccata dal primo. Questo è il caso semplice, ma può diventare più complesso con catene di risorse più lunghe.

La sfida

È necessario scrivere un programma o una funzione in grado di rilevare una possibile situazione di deadlock in un elenco delle risorse a cui accede ogni thread. Questo è code-golf, quindi vince la risposta più breve in byte.

Ogni thread viene avviato contemporaneamente, ma successivamente può essere eseguito in qualsiasi combinazione di interfogliatura. Se ci sono 2 fili con 4 azioni ciascuno, potrebbe essere eseguito come (dove ogni numero è un'azione intrapresa dal filo con quella id) 1,1,1,1,2,2,2,2, 2,2,2,2,1,1,1,1, 1,2,1,2,1,2,1,2, 1,1,2,2,2,2,1,1, o qualsiasi altra combinazione possibile.

Ingresso

Riceverai, tramite STDIN, il parametro della funzione o l'alternativa più vicina, un elenco di stringhe. Ogni stringa sarà nel formato +a -b. Ognuna di queste stringhe rappresenta il blocco ( +) / unlocking ( -) di una risorsa da parte del thread. Tra ogni thread sarà un ---separatore. È garantito che un thread non tenterà di bloccare una risorsa che ha già bloccato e che tutti i thread sbloccheranno esplicitamente tutte le risorse che hanno bloccato prima di uscire. Di seguito è riportato un esempio per dimostrare:

+a    # Lock resource a
+b    # Lock resource b
-a    # Unlock resource a
-b    # Unlock resource b
---   # Thread separator
+b    # Lock resource b
-b    # Unlock resource b

Produzione

L'output deve essere falso se l'input non contiene alcuna possibilità di deadlock e in verità se contiene una possibile situazione di deadlock. Per esempio:

  • true
  • false
  • 1
  • 0

sono tutti output validi, ma qualsiasi cosa chiaramente definita come verità / falsità sarà accettata.

Esempi

+a
-a
---
+a
-a

Produzione: false


+a
+b
-b
-a
---
+b
+a
-a
-b

Produzione true

Deadlock quando si tenta di acquisire b,arispettivamente per i thread1,2


+a
+b
-a
-b
---
+a
+b
-b
-a

Produzione false


+a
+b
-b
-a
---
+b
+c
-c
-b
---
+c
+a
-a
-c

Produzione: true

Deadlock nei thread 1,2,3 quando si tenta di acquisire b,c,arispettivamente.


http://pastebin.com/vMYRZxtW

Produzione false


http://pastebin.com/V5MVgNgS

Produzione true

Deadlock nei thread 1,2,3 quando si tenta di acquisire b,d,arispettivamente.


Naturalmente questo potrebbe diventare molto più complesso, con più thread, più risorse per ognuno e così via, ma credo che questi test coprano le basi.

indennità

Dato che è molto triste quando trovi situazioni di deadlock durante la scrittura di un programma, c'è un bonus di -8 byte per le risposte in uscita :(e rispettivamente :)come verità / falsa.


Sto solo supponendo questo, ma sarebbe bello chiarire che le azioni di ciascun thread (a partire dalla parte superiore del thread) vengono eseguite in parallelo e corrispondono allo stesso orario di sistema
Optimizer,

1
Le azioni vengono eseguite contemporaneamente, ma non è possibile ipotizzare il tempo in cui viene eseguita ogni azione. Potrebbe accadere che i thread vengano effettivamente eseguiti rigorosamente uno dopo l'altro o completamente interfogliati. È possibile che la prima metà del thread 1 venga eseguita, quindi il thread 2 venga eseguito interamente, quindi il thread 1 esegue la seconda metà. E così via. Ho aggiornato la domanda per chiarirlo.
rorlork,

1
Ah va bene, quindi il compito è capire che, data l'eventuale combinazione di tempi di esecuzione del thread, se è possibile un deadlock.
Ottimizzatore

Sì, scusa, non pensavo che potesse lasciare dubbi. In realtà nell'ultimo esempio questo è dimostrato dal momento che il thread 2 non tenta di utilizzare la risorsa dfino a dopo.
rorlork,

1
@rcrmn sei sicuro :)che non dovrebbe essere :(vero o falso ?
Tyilo,

Risposte:


4

Python 2 - 227

Fondamentalmente si assicura che non ci siano loop di "precedenza". Ad esempio nel secondo test, il primo thread ha una a(b)precedenza e il secondo thread ha una b(a)precedenza.

Stavo pensando di riscrivere questo in Pyth poiché penso che funzionerebbe bene con tutte le operazioni di itertools, ma la conversione del regex richiederà del lavoro, quindi per ora posterò questo e forse proverò a convertirlo e pubblicherò un'altra risposta in seguito.

from itertools import*
import re
f=lambda t:any(re.search(r"(.)((.)\3)+\1",''.join(p))for i in product(*[[m.group(1)+m.group(2)for m in re.finditer(r"(\w).*(\w).*\2.*\1",e,16)]for e in t.split('---')])for p in permutations(i))

Questo risponde falso a pastebin.com/V5MVgNgS
Tyilo

@Tyilo Produce True per me; come lo stai facendo esattamente?
KSab,

oh stava leggendo solo una riga per me. Come dovresti eseguirlo?
Tyilo,

@Tyilo Ho cambiato il formato in una funzione che accetta una stringa multilinea come input
KSab

5

Python - 586 539 524 501 485 byte - 8 = 477

Livelli di rientro:

1: 1 space
2: 1 tab
3: 1 tab + 1 space
4: 2 tabs

-

import sys
V=set()
t=[[[]]]
for r in sys.stdin:
 r=r.strip()
 if'---'==r:t.append([[]])
 else:v=r[1:];V.add(v);l=t[-1][-1];t[-1].append(l+[v]if'+'==r[0]else filter(lambda x:x!=v,l))
s=lambda l:s(l[1:])+map(lambda x:(l[0],x),l[1:])if 1<len(l)else[]
E=reduce(set.union,map(lambda x:set(sum(map(s,x),[])),t),set())
for v in V:
 k=set();q=[v]
 while 0<len(q):
    u=q.pop(0)
    if u in k:continue
    k.add(u)
    for x,y in E:
     if u==x:
        if y in k:print':(';sys.exit()
        else:q.append(y)
print':)'

1
Utilizzare ;per combinare le linee rientrate per salvare i caratteri. Allo stesso modo, fai le tue dichiarazioni una fodera.
isaacg,

@isaacg e asso, grazie! Penso di averlo migliorato il più possibile usando i tuoi consigli.
Tyilo,

A proposito, se non ti dispiace reindirizzare l'input da un file (o premendo Ctrl + D due volte), puoi farlo for r in sys.stdininvece difor r in sys.stdin.readlines()
user12205

@ace Non vedo alcun comportamento diverso tra l'uso di just sys.stdino sys.stdin.readlines(), quindi l'ho cambiato, grazie ancora.
Tyilo,

Puoi rimuovere gli spazi tra printe':)'
user12205
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.