デッドロックを見つける


18

デッドロックを見つける

マルチスレッドアプリケーションをプログラミングするときは、共有リソースにアクセスするときにさまざまなスレッドのデッドロックを避けるように注意する必要があります。デッドロックは、スレッドの試みは、他のスレッドが最初でロックされたリソースにアクセスしようとしているのと同時に、別のスレッドでロックされているリソースにアクセスするときに発生します。これは単純なケースですが、より長いリソースチェーンではより複雑になる可能性があります。

チャレンジ

各スレッドがアクセスするリソースのリストで、考えられるデッドロック状況を検出できるプログラムまたは関数を作成する必要があります。これはコードゴルフなので、バイト単位の最短回答が勝ちです。

すべてのスレッドは同時に開始されますが、その後はインターリーブの任意の組み合わせで実行できます。4つのアクションそれぞれ有する2つのスレッドがある場合、それは(各番号はそのIDを持つスレッドによって取られる行動である)として実行することができ1,1,1,1,2,2,2,22,2,2,2,1,1,1,11,2,1,2,1,2,1,21,1,2,2,2,2,1,1、又は任意の他の可能な組み合わせ。

入力

STDIN、関数パラメーター、または最も近い代替手段を介して、文字列のリストを受け取ります。各文字列は、形式になります+a -b。この文字列はすべて、スレッドによるリソースのlocking(+)/ unlocking(-)を表します。すべてのスレッドの間に---セパレータがあります。スレッドが既にロックしているリソースをロックしようとしないこと、およびすべてのスレッドが終了する前にロックしたすべてのリソースを明示的にロック解除することが保証されます。次に例を示します。

+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

出力

入力にデッドロックの可能性が含まれていない場合、出力は偽であり、デッドロックの可能性が含まれている場合は、真実です。例えば:

  • true
  • false
  • 1
  • 0

すべて有効な出力ですが、真実/偽と明確に定義されたものはすべて受け入れられます。

+a
-a
---
+a
-a

出力: false


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

出力 true

b,aスレッドごとに取得しようとするとデッドロック1,2


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

出力 false


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

出力: true

b,c,aそれぞれ取得しようとすると、スレッド1、2、3のデッドロック。


http://pastebin.com/vMYRZxtW

出力 false


http://pastebin.com/V5MVgNgS

出力 true

b,d,aそれぞれ取得しようとしたときのスレッド1、2、3のデッドロック。


もちろん、これはもっと複雑になり、スレッドが増えたり、各スレッドにリソースが増えたりしますが、これらのテストは基本をカバーしていると思います。

ボーナス

プログラムを書いているときにデッドロック状態を見つけるのは非常に悲しいので、回答の出力にはそれぞれ-8バイトのボーナスが:(あり:)、真実/偽として回答します。


私はこれを仮定しているだけですが、各スレッドのアクション(スレッドの先頭から開始)が並行して実行され、同じシステム時間に対応することを明確にするとよいでしょう
オプティマイザー

1
アクションは同時に実行されますが、すべてのアクションが実行される時間を想定することはできません。スレッドが実際に厳密に次々に実行されるか、完全にインターリーブされることがあります。スレッド1の前半が実行され、スレッド2が完全に実行され、スレッド1が後半を実行する場合があります。等々。それを明確にするために質問を更新しました。
ロルク

1
ああ、それで、タスクは、デッドロックが可能かどうか、スレッドの実行時間の可能な組み合わせを考えることです。
オプティマイザー

はい、申し訳ありませんが、私はそれが疑問を残す可能性があるとは思わなかった。実際、最後の例では、スレッド2はd後までリソースを使用しようとしないため、これが示されています。
ロルク

1
@rcrmnは:)、偽と:(真のためではないはずですか?
ティロ

回答:


4

Python 2-227

基本的に、「優先順位」のループがないことを確認します。たとえば、2番目のテストでは、最初のスレッドにa(b)優先順位があり、2番目のスレッドにb(a)優先順位があります。

すべてのitertools操作でうまくいくと思うので、これをPythで書き直すことを考えていましたが、正規表現の変換には多少の作業が必要になるため、今のところこれを投稿し、後で変換して別の回答を投稿しようと思います。

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))

この答えは偽pastebin.com/V5MVgNgS
Tyilo

@Tyilo私にとってはTrueを出力します。どのくらい正確に実行していますか?
KSab

ああ、それは私にとって一行だけを読んでいた。どのように実行するのですか?
ティロー

@Tyilo Iは、入力として複数行の文字列をとる関数であるフォーマットを変更
KSab

5

パイソン- 586 539 524 501 485バイト- 8 = 477

インデントレベル:

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
;インデントされた行を組み合わせて文字を保存するために使用します。同様に、ステートメントを1つのライナーにします。
isaacg

@isaacgとエース、ありがとう!あなたのヒントを使ってできる限り改善したと思います。
ティロ

ところで、ファイルからの入力をパイプすることを気にしない場合(またはCtrl + Dを2回押す)、for r in sys.stdin代わりに行うことができますfor r in sys.stdin.readlines()
-user12205

@ace just sys.stdinまたはを使用しても動作に違いは見られないsys.stdin.readlines()ので、変更しました。ありがとうございます。
ティロ

printとの間のスペースを削除できます':)'
user12205
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.