2009-04-03 4 views
17

Điều gì sẽ xảy ra khi bạn đồng thời mở hai (hoặc nhiều hơn) FileOutputStreams trên cùng một tệp?Tệp đồng thời viết bằng Java trên Windows

Các Java API nói điều này:

Một số nền tảng, đặc biệt, cho phép một tập tin được mở ra cho bằng văn bản chỉ có một FileOutputStream (hoặc đối tượng tập tin văn bản khác) tại một thời điểm.

Tôi đoán Windows không phải là nền tảng như vậy, vì tôi có hai luồng đọc một số tệp lớn (mỗi tệp khác nhau) rồi ghi vào cùng một tệp đầu ra. Không có ngoại lệ nào được ném ra, tệp được tạo và dường như chứa các khối từ cả hai tệp đầu vào.

câu hỏi Side:

  • Đây có phải là đúng đối với Unix, quá?
  • Và vì tôi muốn hành vi giống nhau (thực ra tôi muốn một chủ đề viết chính xác và cái kia được cảnh báo về xung đột), làm cách nào để xác định rằng tệp đã được mở để viết?

Trả lời

16

Không có cách đáng tin cậy, đa nền tảng được thông báo thụ động khi một tệp có một nhà văn khác — tức là, nêu một ngoại lệ nếu một tệp đã được mở để ghi. Tuy nhiên, có một số kỹ thuật giúp bạn chủ động kiểm tra điều này.

Nếu nhiều quá trình (có thể là kết hợp của Java và không phải Java) có thể đang sử dụng tệp, hãy sử dụng FileLock. Chìa khóa để sử dụng khóa tập tin thành công là hãy nhớ rằng chúng chỉ là "tư vấn". Khóa được đảm bảo hiển thị nếu bạn kiểm tra, nhưng nó sẽ không ngăn bạn làm việc với tập tin nếu bạn quên. Tất cả các quy trình truy cập tệp phải được thiết kế để sử dụng giao thức khóa.

Nếu một quá trình Java đơn lẻ hoạt động với tệp, bạn có thể sử dụng các công cụ đồng thời được tích hợp sẵn trong Java để thực hiện việc này một cách an toàn. Bạn cần một bản đồ hiển thị cho tất cả các chủ đề liên kết từng tên tệp với cá thể khóa tương ứng của nó. Câu trả lời cho a related question có thể được điều chỉnh dễ dàng để thực hiện việc này với các đối tượng File hoặc canonical paths đối với tệp. Đối tượng khóa có thể là FileOutputStream, một số trình bao bọc xung quanh luồng hoặc ReentrantReadWriteLock.

4

Tôi sẽ cảnh giác để hệ điều hành xác định trạng thái tệp cho bạn (vì đây là tùy thuộc vào hệ điều hành). Nếu bạn có tài nguyên được chia sẻ, tôi sẽ hạn chế quyền truy cập vào tài khoản đó bằng cách sử dụng một số Re-entrant lock

Sử dụng khóa này nghĩa là một chủ đề có thể lấy tài nguyên (tệp) và ghi vào đó. Chủ đề tiếp theo có thể kiểm tra khóa này đang được giữ bởi một luồng khác và/hoặc chặn vô thời hạn cho đến khi luồng đầu tiên giải phóng nó.

Windows (Tôi nghĩ) sẽ hạn chế hai quy trình ghi vào cùng một tệp. Tôi không tin rằng Unix sẽ làm như vậy.

+0

Nhưng tôi không muốn chặn bất cứ khi nào tôi viết, tôi muốn chặn, nếu ai đó đã viết thư cho tệp tôi muốn viết. Thực ra, tôi không muốn chặn chút nào. Tôi muốn nói với chủ đề thứ hai rằng anh ta không thể viết và để cho khách hàng quyết định về hành động tiếp theo. –

+0

Kiểm tra khóa API. Bạn sẽ có thể kiểm tra khóa để xác định xem ai đó đã khóa nó (tức là không bock) và sau đó quyết định phải làm gì –

1

Nếu 2 chủ đề bạn đang nói đến nằm trong cùng một JVM, thì bạn có thể có biến boolean ở đâu đó được truy cập bởi cả hai luồng.

1

Unix cho phép các tác giả đồng thời cùng một tệp.

Bạn không nên cố ghi vào cùng một tệp nhiều lần. Nếu bạn là bạn có một lỗ hổng thiết kế.