2010-01-11 16 views
12

Tôi có một số chủ đề (một số trong số đó được sinh ra bởi Quy trình X, một số khác bằng Process Y, et cetera) và mỗi chuỗi cần phải ghi vào một tệp MyFile. Tuy nhiên, nếu Thread T1 bắt đầu viết thành MyFile trước tiên, khi Thread T2 bắt đầu viết, cần phải chờ T1 để phát hành tệp để có thể đọc nội dung được viết trong Thread T1. Nói cách khác, mỗi chủ đề sẽ có một phương pháp finalizeThread, như vậy:Khóa tệp Java

private void finalizeThread() { 
    File f = new File("MyFile.dat"); 
    f.createNewFile(); // atomically creates the file, if it doesn't exist 
    locked_section { 
     readContentsFromFile(f); // read contents if some other thread already modified the file 
     modifyContentsFromFile(f); // modify 
     writeFile(f); // write, so that new threads can see the content modified by this thread 
    } 
} 

Câu hỏi của tôi là: Làm thế nào tôi có thể thực hiện các locked_section trong đoạn code trên? Tôi đã nhìn vào lớp FileLock, nhưng nó nói trong Javadoc rằng "Khóa tệp được tổ chức thay mặt cho toàn bộ máy ảo Java. Chúng không thích hợp để kiểm soát quyền truy cập vào tệp theo nhiều luồng trong cùng một máy ảo.".

+0

bạn có chắc chắn rằng bạn thực sự muốn phương thức finalize() không? – Dmitry

+0

Không, tên của phương thức không thực sự là 'finalize'. Đó là một phương thức/gọi lại được gọi sau chuỗi (thực ra, một tập hợp các luồng, nhưng điều này không liên quan đến trường hợp) được hoàn thành với công việc của nó, vì tôi không sử dụng các luồng API Java Concurrency chuẩn. Tôi sẽ đổi tên nó để tránh nhầm lẫn với 'Object # finalize'. –

Trả lời

12

Nếu tệp chỉ được truy cập từ chương trình của bạn, đối tượng khóa được đồng bộ hóa sẽ ổn. Nhưng nếu bạn muốn bảo vệ tập tin không bị thay đổi bởi các chương trình khác trong khi bạn đang làm việc trên nó, bạn có thể sử dụng tính năng khóa tập tin của Java trong java.nio.channels.FileLock (example). Như văn bản nói, hãy nhớ rằng trên một số hệ điều hành, các chương trình vẫn có thể thay đổi tệp nếu chúng không kiểm tra khóa tệp hiện có.

+0

Cảm ơn phản hồi. Có, nó chỉ được truy cập bởi chương trình của tôi, và mỗi thread sẽ/có thể kiểm tra sự tồn tại của một khóa trước khi tiếp tục. Vấn đề là API mà tôi đang sử dụng có thể sinh ra các luồng từ nhiều tiến trình khác nhau, và một số luồng từ bên trong cùng một luồng, và tôi sợ có thể có vấn đề liên quan đến điều đó, vì javadoc 'FileLock' đề cập đến nó. –

+0

Có lẽ tôi hiểu nhầm điều gì đó, nhưng ý bạn là bạn có chủ đề sinh ra bởi các quy trình khác nhau? Một tiến trình có không gian địa chỉ riêng của nó và bất kỳ luồng nào mà nó tạo ra sẽ chia sẻ không gian địa chỉ đó. Bạn có nhiều quy trình mỗi lần sinh ra nhiều luồng có thể cố gắng ghi vào cùng một tệp không? –

+2

Javadoc nói: "Khóa tệp được giữ thay mặt cho toàn bộ máy ảo Java.Chúng không thích hợp để kiểm soát quyền truy cập vào một tệp bằng nhiều luồng trong cùng một máy ảo. Các đối tượng khóa tập tin được an toàn để sử dụng bởi nhiều chủ đề đồng thời. " Không phải là hai câu cuối cùng loại trừ lẫn nhau? Tôi nghĩ ai đó sẽ phải xem mã nguồn ... Trong đoạn tiếp theo nói rằng "API khóa tệp này được thiết kế để ánh xạ trực tiếp tới cơ sở khóa gốc của hệ điều hành cơ bản." Vì vậy, nó * nên * hoạt động giống như đàn (Linux) hoặc LockFileEx (Windows) – AndiDog

0

Bạn sẽ muốn đồng bộ hóa trên một số đối tượng. Ví dụ:

synchronized(fileLockObject) { 
    readContentsFromFile(f); 
    modifyContentsFromFile(f); 
    writeFile(f); 
} 
+1

Xin chào Anon., Cảm ơn vì bình luận của bạn. Tuy nhiên, tôi không thể làm điều đó, vì các chủ đề này được sinh ra bởi các quy trình khác nhau, và tôi không thể chia sẻ đối tượng đó giữa tất cả các luồng, do đó cần một cách tiếp cận khác. Đây cũng không phải là các chủ đề Java 'concurrency. *' Chuẩn, nhưng các luồng được tạo bởi một API Oracle. –

+0

Nếu chúng là các quá trình khác nhau (và do đó các máy ảo riêng biệt), bạn chỉ có thể sử dụng lớp 'FileLock'. –

+0

Có, nhưng một số được sinh ra bởi cùng một quá trình. Nhưng có, có lẽ một chiến lược lai sẽ hoạt động. Cảm ơn. –

2

Thay vì chia sẻ khóa, có thể bạn có thể có một quy trình riêng biệt chịu trách nhiệm duy trì khóa trên tệp. Để bắt đầu đọc/sửa đổi/ghi bước của bạn, một chủ đề sẽ phải hỏi quá trình trung tâm này cho khóa thông qua HTTP, hoặc nhắn tin, hoặc bất cứ điều gì bạn thích. Nếu yêu cầu bị từ chối, Chủ đề sẽ chuyển sang chế độ ngủ, thức dậy và thử lại. Nếu không, Thread sẽ đọc/sửa đổi/ghi và sau đó nói với quá trình khóa rằng nó đang giải phóng khóa.

+1

Nếu bạn định sử dụng quy trình trung tâm, có lẽ tốt hơn nếu quá trình này xử lý việc đọc/ghi, vì vậy bạn không phải lo lắng về những gì xảy ra khi một chuỗi bị chết sau khi được cấp khóa (bạn cũng vậy, nhưng nó ít phức tạp hơn). – wds

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