Tìm kiếm bế tắc


18

Tìm kiếm bế tắc

Khi lập trình một ứng dụng đa luồng, người ta phải cẩn thận để tránh bế tắc các luồng khác nhau khi truy cập các tài nguyên được chia sẻ. Sự bế tắc xảy ra khi một luồng cố gắng truy cập vào một tài nguyên bị khóa trong một luồng khác cùng lúc với luồng khác đang cố gắng truy cập vào một tài nguyên bị khóa bởi lần đầu tiên. Đây là trường hợp đơn giản, nhưng nó có thể phức tạp hơn với chuỗi tài nguyên dài hơn.

Các thách thức

Bạn nên viết một chương trình hoặc hàm có thể phát hiện tình huống bế tắc có thể xảy ra trong danh sách các tài nguyên được truy cập bởi mỗi luồng. Đây là môn đánh gôn, vì vậy câu trả lời ngắn nhất bằng byte thắng.

Mọi luồng được bắt đầu cùng một lúc, nhưng sau đó chúng có thể chạy ở bất kỳ kết hợp xen kẽ nào. Nếu có 2 bài với 4 hành động mỗi, nó có thể được chạy như (trong đó mỗi số là một hành động thực hiện bởi các chủ đề với 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, hoặc bất kỳ sự kết hợp có thể khác.

Đầu vào

Bạn sẽ nhận được, thông qua STDIN, tham số hàm hoặc thay thế gần nhất, một danh sách các chuỗi. Mỗi chuỗi sẽ ở định dạng +a -b. Mỗi một chuỗi này đại diện cho khóa ( +) / mở khóa ( -) của tài nguyên theo luồng. Giữa mỗi luồng sẽ là một ---dải phân cách. Đảm bảo rằng một luồng sẽ không cố khóa tài nguyên mà nó đã bị khóa và tất cả các luồng sẽ mở khóa rõ ràng tất cả các tài nguyên mà chúng đã khóa trước khi thoát. Sau đây là một ví dụ để chứng minh:

+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

Đầu ra

Đầu ra sẽ bị sai lệch nếu đầu vào không chứa bất kỳ khả năng bế tắc nào và sự thật nếu nó có thể xảy ra tình huống bế tắc. Ví dụ:

  • true
  • false
  • 1
  • 0

là tất cả các kết quả đầu ra hợp lệ, nhưng bất cứ điều gì được xác định rõ ràng là trung thực / giả mạo sẽ được chấp nhận.

Ví dụ

+a
-a
---
+a
-a

Đầu ra: false


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

Đầu ra true

Bế tắc khi cố gắng để có được b,atương ứng cho chủ đề1,2


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

Đầu ra false


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

Đầu ra: true

Bế tắc trong chủ đề 1,2,3 khi cố gắng để có được b,c,atương ứng.


http://pastebin.com/vMYRZxtW

Đầu ra false


http://pastebin.com/V5MVgNgS

Đầu ra true

Bế tắc trong luồng 1,2,3 khi cố gắng để b,d,atương ứng.


Tất nhiên điều này có thể phức tạp hơn nhiều, với nhiều luồng hơn, nhiều tài nguyên hơn cho mỗi thứ, v.v., nhưng tôi tin rằng các thử nghiệm này bao gồm những điều cơ bản.

Tặng kem

Vì rất buồn khi bạn tìm thấy các tình huống bế tắc khi viết chương trình, có phần thưởng -8 byte cho các câu trả lời xuất ra :(:)tương ứng là sự thật / giả.


Tôi chỉ giả sử điều này, nhưng sẽ rất tốt để làm rõ rằng các hành động của từng luồng (bắt đầu từ đầu chuỗi) được chạy song song và tương ứng với cùng thời gian hệ thống
Trình tối ưu hóa

1
Các hành động được chạy đồng thời, nhưng thời gian mà mọi hành động được chạy không thể được giả định. Nó có thể xảy ra rằng các chủ đề thực sự được chạy một cách nghiêm ngặt sau khi khác hoặc hoàn toàn xen kẽ. Có thể là nửa đầu của luồng 1 được chạy, sau đó luồng 2 được chạy hoàn toàn, sau đó luồng 1 chạy nửa thứ hai. Và như thế. Tôi đã cập nhật câu hỏi để làm rõ điều đó.
rorlork

1
À không sao, vì vậy, nhiệm vụ là tìm ra bất kỳ sự kết hợp nào có thể của thời gian chạy luồng, cho dù có thể bế tắc hay không.
Tối ưu hóa

Vâng, xin lỗi, tôi không nghĩ rằng có thể để lại nghi ngờ. Trên thực tế trong ví dụ cuối, điều này được thể hiện do luồng 2 không cố sử dụng tài nguyên dcho đến sau này.
rorlork

1
@rcrmn bạn có chắc :)không nên sai và :(đúng không?
Tyilo

Câu trả lời:


4

Con trăn 2 - 227

Về cơ bản đảm bảo không có vòng lặp 'ưu tiên'. Ví dụ, trong thử nghiệm thứ hai, luồng đầu tiên có a(b)quyền ưu tiên và luồng thứ hai có b(a)quyền ưu tiên.

Tôi đã suy nghĩ về việc viết lại cái này trong Pyth vì tôi nghĩ nó sẽ hoạt động tốt với tất cả các hoạt động của itertools, nhưng việc chuyển đổi regex sẽ mất một số công việc vì vậy bây giờ tôi sẽ đăng bài này và có thể thử chuyển đổi nó và đăng câu trả lời khác sau.

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

Điều này trả lời sai cho pastebin.com/V5MVgNgS
Tyilo

@Tyilo Nó xuất ra Đúng cho tôi; chính xác thì bạn đang chạy nó như thế nào?
KSab

oh nó chỉ đọc một dòng cho tôi Làm thế nào bạn có nghĩa vụ để chạy nó?
Tyilo

@Tyilo Tôi đã thay đổi định dạng thành một hàm lấy chuỗi đa dòng làm đầu vào
KSab

5

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

Cấp độ thụt:

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
Sử dụng ;để kết hợp các dòng được thụt lề để lưu các ký tự. Tương tự như vậy, làm cho báo cáo của bạn một lót.
isaacg

@isaacg và ace, Cảm ơn! Tôi nghĩ rằng tôi đã cải thiện nó nhiều nhất có thể bằng các mẹo của bạn.
Tyilo

BTW nếu bạn không nhớ đường ống đầu vào từ một tệp (hoặc nhấn Ctrl + D hai lần) thì bạn có thể thực hiện for r in sys.stdinthay vìfor r in sys.stdin.readlines()
user12205

@ace Tôi không thấy bất kỳ hành vi khác nhau giữa việc sử dụng chỉ sys.stdinhoặc sys.stdin.readlines(), vì vậy tôi đã thay đổi nó, cảm ơn một lần nữa.
Tyilo

Bạn có thể xóa khoảng trắng giữa print':)'
user12205
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.