Trouver l'impasse

18

Trouver l'impasse

Lors de la programmation d'une application multithreading, il faut veiller à éviter de bloquer les différents threads lors de l'accès aux ressources partagées. Un blocage se produit lorsqu'un thread tente d'accéder à une ressource qui est verrouillée dans un autre thread en même temps que l'autre thread tente d'accéder à une ressource verrouillée par le premier. C'est le cas simple, mais il peut devenir plus complexe avec des chaînes de ressources plus longues.

Le défi

Vous devez écrire un programme ou une fonction qui peut détecter une situation de blocage possible dans une liste des ressources accessibles par chaque thread. C'est le code-golf, donc la réponse la plus courte en octets l'emporte.

Chaque thread est démarré en même temps, mais après cela, ils peuvent s'exécuter à n'importe quelle combinaison d'entrelacement. S'il y a 2 fils avec 4 actions chacun, il pourrait être exécuté comme (où chaque nombre est une mesure prise par le fil avec cet identifiant) 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, ou toute autre combinaison possible.

Contribution

Vous recevrez, via STDIN, le paramètre de fonction ou l'alternative la plus proche, une liste de chaînes. Chaque chaîne sera au format +a -b. Chacune de ces chaînes représente le verrouillage ( +) / déverrouillage ( -) d'une ressource par le thread. Entre chaque fil sera un ---séparateur. Il est garanti qu'un thread ne tentera pas de verrouiller une ressource qu'il a déjà verrouillée et que tous les threads déverrouilleront explicitement toutes les ressources qu'ils ont verrouillées avant de quitter. Voici un exemple pour démontrer:

+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

Production

La sortie doit être fausse si l'entrée ne contient aucune possibilité de blocage et véridique si elle contient une situation de blocage possible. Par exemple:

  • true
  • false
  • 1
  • 0

sont toutes des sorties valides, mais tout ce qui est clairement défini comme véridique / falsifié sera accepté.

Exemples

+a
-a
---
+a
-a

Production: false


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

Production true

Blocage lors de la tentative d'acquisition b,arespectivement pour les threads1,2


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

Production false


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

Production: true

Blocage dans les threads 1,2,3 lors de la tentative d'acquisition b,c,arespectivement.


http://pastebin.com/vMYRZxtW

Production false


http://pastebin.com/V5MVgNgS

Production true

Blocage dans les threads 1,2,3 lorsque vous essayez d'acquérir b,d,arespectivement.


Bien sûr, cela pourrait devenir beaucoup plus complexe, avec plus de threads, plus de ressources pour chacun, etc., mais je pense que ces tests couvrent les bases.

Prime

Puisqu'il est très triste de trouver des situations de blocage lors de l'écriture d'un programme, il y a un bonus de -8 octets pour les réponses générées :(et :)comme véridiques / fausses respectivement.

rorlork
la source
Je suppose que cela, mais il serait bien de clarifier que les actions de chaque thread (à partir du haut du thread) sont exécutées en parallèle et correspondent à la même heure système
Optimizer
1
Les actions sont exécutées simultanément, mais le temps dans lequel chaque action est exécutée ne peut pas être supposé. Il peut arriver que les threads soient exécutés strictement l'un après l'autre ou complètement entrelacés. Il se peut que la première moitié du thread 1 soit exécutée, puis le thread 2 est entièrement exécuté, puis le thread 1 exécute sa seconde moitié. Etc. J'ai mis à jour la question pour clarifier cela.
rorlork
1
Ah d'accord, la tâche consiste donc à déterminer que, compte tenu de toute combinaison possible de temps d'exécution des threads, si un blocage est possible.
Optimizer
Oui, désolé, je ne pensais pas que cela pouvait laisser des doutes. En fait, dans le dernier exemple, cela est démontré car le thread 2 n'essaie d'utiliser la ressource dque plus tard.
rorlork
1
@rcrmn êtes-vous sûr que vous :)ne devriez pas être pour faux et :(pour vrai?
Tyilo

Réponses:

4

Python 2 - 227

S'assure fondamentalement qu'il n'y a pas de boucles de «priorité». Par exemple, dans le deuxième test, le premier thread a une a(b)priorité et le second thread a une b(a)priorité.

Je pensais à réécrire cela en Pyth car je pense que cela fonctionnerait bien avec toutes les opérations itertools, mais la conversion de l'expression régulière prendra un certain travail, donc pour l'instant je publierai ceci et j'essaierai peut-être de le convertir et de publier une autre réponse plus tard.

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))
KSab
la source
Cela répond faux à pastebin.com/V5MVgNgS
Tyilo
@Tyilo Il produit True pour moi; comment l'exécutez-vous exactement?
KSab
oh, il ne lisait qu'une seule ligne pour moi. Comment êtes-vous censé le faire fonctionner?
Tyilo
@Tyilo J'ai changé le format pour être une fonction qui prend une chaîne multiligne en entrée
KSab
5

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

Niveaux d'indentation:

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':)'
Tyilo
la source
1
Permet ;de combiner des lignes en retrait pour enregistrer des caractères. De même, faites vos déclarations d'une ligne.
isaacg
@isaacg et ace, merci! Je pense que je l'ai amélioré autant que possible en utilisant vos conseils.
Tyilo
BTW si cela ne vous dérange pas de canaliser l'entrée à partir d'un fichier (ou d'appuyer deux fois sur Ctrl + D), vous pouvez le faire à la for r in sys.stdinplace defor r in sys.stdin.readlines()
user12205
@ace Je ne vois aucun comportement différent entre utiliser juste sys.stdinou sys.stdin.readlines(), donc je l'ai changé, merci encore.
Tyilo
Vous pouvez supprimer les espaces entre printet':)'
user12205