2010-10-14 56 views
5

Đọc bế tắc đó có thể xảy ra trong một chương trình java đơn luồng. Tôi tự hỏi làm thế nào kể từ khi sẽ không có bất kỳ cạnh tranh sau khi tất cả. Theo như tôi có thể nhớ, sách minh họa các ví dụ có nhiều hơn một chủ đề. Bạn có thể vui lòng đưa ra một ví dụ nếu nó có thể xảy ra với một sợi đơn.Bế tắc trong một chương trình java đơn luồng

Trả lời

0

số

Khóa chết là kết quả của nhiều luồng (hoặc quy trình) cố gắng lấy khóa theo cách không thể tiếp tục.

Xem xét một trích dẫn từ các bài viết Wikipedia: (http://en.wikipedia.org/wiki/Deadlock)

"Khi hai xe lửa tiến lại gần nhau tại một ngã tư, cả hai sẽ đi đến một dấu chấm và không chịu trách nhiệm bắt đầu lên một lần nữa cho đến khi người kia đã biến mất."

+0

Nhiều chủ đề hoặc * quy trình * .... – NVRAM

+0

Điểm tốt Carter. Tôi đã chỉnh sửa bình luận của mình. Cảm ơn. – philipk

+0

Có, tốt, nhiều (nghĩa là hơn 0) chủ đề, đó là những gì chúng ta đang nói đến. – Ingo

0

Không, âm thanh không thể đối với tôi.

Nhưng về lý thuyết bạn có thể khóa tài nguyên hệ thống trong khi ứng dụng khác khóa một tài nguyên khác mà bạn sắp yêu cầu và ứng dụng đó sẽ yêu cầu ứng dụng bạn đã khóa. Bang Bế tắc.

Nhưng hệ điều hành sẽ có thể sắp xếp điều này bằng cách phát hiện và cung cấp cả hai tài nguyên cho một ứng dụng tại thời điểm đó. Cơ hội cho điều này xảy ra là không hề mỏng, nhưng bất kỳ hệ điều hành tốt nào cũng có thể xử lý cơ hội một tỷ người này.

Nếu bạn thiết kế cẩn thận và chỉ khóa một tài nguyên tại một thời điểm, điều này không thể xảy ra.

+0

Tại sao lại là downvote? Câu trả lời này là chính xác thảo luận về một điều có thể xảy ra một lần trong một tỷ. – Frank

+0

Tôi đã không bỏ phiếu cho bạn, nhưng tôi gần như đã làm. Đoạn 2 của bạn là chính xác, do đó cơ hội xảy ra điều này là rất cao nếu thiết kế của (các) ứng dụng hoạt động theo cách bạn mô tả. Vì vậy, đoạn thứ 3 của bạn là _wrong_ (đối với hầu hết các tài nguyên trên hầu hết hệ điều hành). Sau khi tất cả, ** chính xác những gì hệ điều hành sẽ làm gì để tránh bế tắc? ** – NVRAM

+0

Và đoạn thứ 3 của bạn giả định rằng ứng dụng có thể thực hiện mục tiêu của nó chỉ với một tài nguyên duy nhất, mà chỉ đơn giản là không làm việc cho một số lượng lớn các vấn đề. – NVRAM

6

Đó là vấn đề chính xác bạn định nghĩa "bế tắc" như thế nào.

Ví dụ: trường hợp này hơi thực tế: một ứng dụng đơn luồng sử dụng hàng đợi có giới hạn kích thước chặn khi đạt đến giới hạn của nó. Miễn là giới hạn không đạt được, điều này sẽ làm việc tốt với một sợi đơn. Nhưng khi đạt đến giới hạn, luồng sẽ đợi mãi mãi cho một chuỗi khác (không tồn tại) để lấy thứ gì đó từ hàng đợi để nó có thể tiếp tục.

+3

Tôi không nghĩ đây là bế tắc. Hoặc khác 'while (true) {}' là bế tắc – Bozho

+0

@Bozho Đó là một khối, không phải là bế tắc, nhưng 'while (true)' không liên quan gì đến nó cả. – EJP

1

Vâng, tôi dám nói có

Nếu bạn cố gắng để có được các khóa giống nhau trong cùng một sợi liên tục, nó phụ thuộc vào loại khóa hoặc khóa thực hiện cho dù đó kiểm tra nếu khóa được mua lại bởi cùng một chủ đề. Nếu việc thực hiện không kiểm tra điều này, bạn có một bế tắc.

Để đồng bộ hóa điều này được chọn, nhưng tôi không thể tìm thấy sự đảm bảo cho Semaphore.

Nếu bạn sử dụng một số loại khóa khác, bạn phải kiểm tra thông số như cách đảm bảo hoạt động!

Cũng như đã được chỉ ra, bạn có thể chặn (khác với bế tắc) bằng cách đọc/ghi vào bộ đệm bị hạn chế. Ví dụ bạn viết những thứ vào một bộ đệm rãnh và chỉ đọc từ nó trên một số điều kiện nhất định. Khi bạn không còn có thể chèn, bạn đợi cho đến khi một vị trí trở nên miễn phí, điều này sẽ không xảy ra do bản thân bạn thực hiện việc đọc.

Vì vậy, tôi dám trả lời câu trả lời là có, mặc dù không dễ dàng và thường dễ phát hiện hơn.

hth

Mario

2

Trước khi xử lý đa lõi trở nên rẻ, tất cả các máy tính để bàn có bộ vi xử lý lõi đơn. Các bộ vi xử lý lõi đơn chỉ chạy trên luồng. Vậy làm thế nào đa luồng làm việc sau đó? Việc thực hiện đơn giản nhất cho Java sẽ là: Mã

thread1 của:

doSomething(); 
yield(); // may switch to another thread 
doSomethingElse(); 

đang thread2 của:

doSomething2(); 
yield(); // may switch to another thread 
doSomethingElse2(); 

này được gọi là đa luồng hợp tác - tất cả được thực hiện chỉ với 1 chủ đề, và do đó đa luồng là được thực hiện trong Windows 3.1.

Đa luồng ngày nay được gọi là đa luồng ưu tiên chỉ là một sửa đổi nhỏ về đa luồng hợp tác trong đó năng suất() này được gọi tự động theo thời gian.

Tất cả những gì có thể làm giảm đến interlacings sau:

doSomething(); 
doSomething2(); 
doSomethingElse2(); 
doSomethingElse(); 

hay:

doSomething(); 
doSomething2(); 
doSomethingElse(); 
doSomethingElse2(); 

Và vân vân ... Chúng tôi chuyển đổi đang multithreaded mã đơn luồng. Vì vậy, có, nếu một bế tắc là có thể trong các chương trình đa luồng trong đơn luồng là tốt. Ví dụ:

thread1:

queue.put(x); 
yield(); 

thread2:

x = queue.waitAndGet() 
yield(); 

Đó là OK với interlace này:

queue.put(x); 
x = queue.waitAndGet() 

Nhưng ở đây chúng tôi có được bế tắc:

x = queue.waitAndGet() 
queue.put(x); 

Vì vậy, có, deadlocks là có thể trong các chương trình đơn luồng.

+0

Điểm rất tốt –

+0

Không phải bế tắc đó sẽ xảy ra mỗi lần? – Frank

+0

Với 2 chủ đề đó và năng suất() nó sẽ xảy ra ngẫu nhiên, với hệ điều hành hiện đại (không sử dụng năng suất() nhưng luồng ưu tiên) sẽ hoạt động, với giải pháp đơn luồng thứ hai, bế tắc sẽ xảy ra mọi lúc, chỉ cần thay thế phương thức 'queue.xxxx()' bằng các phương thức thích hợp từ BlockingQueue. Chủ đề sẽ nghĩ rằng nó chờ đợi cho một số chủ đề khác, trong khi nó chờ đợi cho chính nó. :-) – iirekm

1

Ngay cả khi công cụ java của bạn là đơn luồng vẫn có trình xử lý tín hiệu, được thực thi trong một luồng/ngữ cảnh khác với chuỗi chính.

Vì vậy, một bế tắc thực sự có thể xảy ra ngay cả trên các giải pháp đơn luồng, nếu/khi java đang chạy trên Linux.

QED. -pbr

+0

+1 không nghĩ về tín hiệu! –

-1

Nó thực sự là khá dễ dàng:

BlockingQueue bq = new ArrayBlockingQueue(1); 
bq.take(); 

sẽ bế tắc.

+0

Đây không phải là bế tắc. Nó là một khối. – EJP

+0

@EJP Nitpicking. Chủ đề thực hiện điều này đã chết. Quá dễ. – Ingo

Các vấn đề liên quan