2009-02-23 40 views
155

Nếu tôi có một lớp util với các phương thức tĩnh sẽ gọi hàm Hibernate để thực hiện truy cập dữ liệu cơ bản. Tôi tự hỏi nếu làm cho phương pháp synchronized là cách tiếp cận đúng để đảm bảo an toàn luồng.Các phương thức tĩnh được đồng bộ hóa hoạt động như thế nào trong Java?

Tôi muốn điều này ngăn chặn quyền truy cập thông tin vào cùng một cá thể DB. Tuy nhiên, bây giờ tôi chắc chắn nếu mã sau đang ngăn chặn getObjectById được gọi cho tất cả các Lớp khi nó được gọi bởi một lớp cụ thể.

public class Utils { 
    public static synchronized Object getObjectById (Class objclass, Long id) { 
      // call hibernate class 
     Session session = new Configuration().configure().buildSessionFactory().openSession(); 
     Object obj = session.load(objclass, id); 
     session.close(); 
     return obj; 
    } 

    // other static methods 
} 

Trả lời

127

bằng cách sử dụng đồng bộ trên một phương pháp tĩnh khóa bạn sẽ synchronize the class methods and attributes (như trái ngược với phương pháp dụ và các thuộc tính)

Vì vậy, giả định của bạn là chính xác.

Tôi tự hỏi liệu việc đồng bộ hóa phương pháp có phải là cách tiếp cận đúng để đảm bảo an toàn luồng không.

Không thực sự. Bạn nên để cho công việc đó làm RDBMS của bạn để thay thế. Họ giỏi loại đồ này.

Điều duy nhất bạn sẽ nhận được bằng cách đồng bộ hóa quyền truy cập vào cơ sở dữ liệu là làm cho ứng dụng của bạn cực kỳ chậm. Hơn nữa, trong mã bạn đăng, bạn đang xây dựng một Nhà máy phiên mỗi lần, theo cách đó, ứng dụng của bạn sẽ dành nhiều thời gian truy cập vào DB hơn là thực hiện công việc thực tế.

Hãy tưởng tượng kịch bản sau đây:

Khách hàng A và B cố gắng để chèn thông tin khác nhau vào kỷ lục X của bảng T.

Với cách tiếp cận của bạn là điều duy nhất bạn đang nhận được là để đảm bảo một được gọi là sau khi khác, khi điều này sẽ xảy ra anyway trong DB, bởi vì RDBMS sẽ ngăn cản họ chèn một nửa thông tin từ A và một nửa từ B cùng một lúc. Kết quả sẽ giống nhau nhưng chỉ chậm hơn 5 lần (hoặc nhiều hơn).

Có lẽ tốt hơn là hãy xem chương "Transactions and Concurrency" trong tài liệu Hibernate. Hầu hết các vấn đề bạn đang cố gắng giải quyết, đã được giải quyết và một cách tốt hơn nhiều.

+1

Câu trả lời rất hữu ích! Vì vậy, Hibernate chăm sóc cnocurrency bởi "khóa lạc quan". Sau đó, không cần phải sử dụng "đồng bộ" phương pháp ở tất cả để giải quyết bất kỳ concurrecy truy cập dữ liệu ?? Sử dụng các phương thức "đồng bộ" chỉ khi dữ liệu không được lưu trữ trong cơ sở dữ liệu ?? .. khi nào bạn sử dụng chúng? – tomato

+1

1) Tôi nghĩ rằng có một số phương tiện để sử dụng khóa bi quan quá. 2) Không, RDBMS có thể làm việc đó. 3) Nếu dữ liệu được truy cập bởi nhiều luồng cùng một lúc. 4) đồng bộ hóa hữu ích khi hai luồng phải chia sẻ dữ liệu. Nếu họ không cần, thì tốt hơn nhiều! – OscarRyz

+7

Bất kỳ nhà hàng thức ăn nhanh nào đều sử dụng đa luồng. Một chuỗi sẽ đưa bạn đặt hàng và sử dụng một chuỗi khác để chuẩn bị và tiếp tục với khách hàng tiếp theo. Điểm đồng bộ chỉ hoạt động khi họ trao đổi thông tin để biết chuẩn bị những gì. Theo một mô hình như thế thực sự đơn giản hóa cuộc sống. – OscarRyz

16

Phương pháp tĩnh sử dụng lớp làm đối tượng khóa, là Utils.class cho ví dụ của bạn. Vì vậy, có, nó là OK.

2

Nếu nó liên quan đến dữ liệu trong cơ sở dữ liệu của bạn, tại sao không sử dụng khóa tách biệt cơ sở dữ liệu để đạt được?

+0

Tôi không có bất kỳ nền cơ sở dữ liệu nào. Bây giờ tôi biết !! Cảm ơn đã chỉ ra điều đó! :) – tomato

2

Để trả lời câu hỏi của bạn, có: phương pháp synchronized của bạn không thể được thực hiện bởi nhiều hơn một chuỗi tại một thời điểm.

9

Tại sao bạn muốn thực thi rằng chỉ một luồng duy nhất mới có thể truy cập vào DB cùng một lúc?

Đây là công việc của trình điều khiển cơ sở dữ liệu để thực hiện bất kỳ khóa cần thiết nào, giả sử Connection chỉ được sử dụng bởi một chuỗi tại một thời điểm!

Nhiều khả năng, cơ sở dữ liệu của bạn là hoàn toàn có khả năng xử lý nhiều, song song truy cập

+0

Tôi cá cược nó là/là một giải pháp cho một số vấn đề giao dịch. Tức là, giải pháp không giải quyết được vấn đề thực sự –

+1

Tôi không biết điều đó .... Tôi nghĩ tôi sẽ phải tự thực hiện điều này. Cảm ơn đã chỉ ra điều đó! :) – tomato

205

Để giải quyết câu hỏi thường xuyên hơn ...

Hãy ghi nhớ rằng việc sử dụng đồng bộ về phương pháp thực sự chỉ là viết tắt (giả định lớp là SomeClass):

synchronized static void foo() { 
    ... 
} 

cũng giống như

static void foo() { 
    synchronized(SomeClass.class) { 
     ... 
    } 
} 

synchronized void foo() { 
    ... 
} 

được giống như

void foo() { 
    synchronized(this) { 
     ... 
    } 
} 

Bạn có thể sử dụng bất kỳ đối tượng nào làm khóa. Nếu bạn muốn khóa các tập con của phương pháp tĩnh, bạn có thể

class SomeClass { 
    private static final Object LOCK_1 = new Object() {}; 
    private static final Object LOCK_2 = new Object() {}; 
    static void foo() { 
     synchronized(LOCK_1) {...} 
    } 
    static void fee() { 
     synchronized(LOCK_1) {...} 
    } 
    static void fie() { 
     synchronized(LOCK_2) {...} 
    } 
    static void fo() { 
     synchronized(LOCK_2) {...} 
    } 
} 

(cho các phương pháp không tĩnh, bạn sẽ muốn làm cho ổ khóa có lĩnh vực không tĩnh)

+7

Bốn khối mã hàng đầu đó là vàng. Chính xác những gì tôi đang tìm kiếm. Cảm ơn bạn. –

+0

Có đúng không nếu tôi sử dụng Khóa tĩnh trên phương pháp không tĩnh, không có hai đối tượng của lớp SomeClass sẽ có thể chạy cùng một lúc? – Samuel

+2

@Samuel - Hầu như ... Đó là nhiều hơn về chủ đề hơn so với trường hợp đối tượng. Bạn đang đúng trong trường hợp riêng biệt của SomeClass tất cả sẽ sử dụng cùng một khóa/màn hình: một liên kết với đối tượng Someclass.class. Vì vậy, nếu hai chủ đề khác nhau được xử lý hai trường hợp khác nhau của SomeClass, cả hai đều không thể chạy cùng một lúc. Tuy nhiên, nếu một luồng đơn gọi là một phương thức trong một thể hiện của SomeClass, và phương thức đó được gọi là một phương thức trong trường hợp khác, thì sẽ không có sự ngăn chặn nào xảy ra. –

13

static synchronized nghĩa giữ khóa trên các đối tượng Class của lớp học ở đâu là synchronized có nghĩa là giữ khóa trên chính đối tượng của lớp đó. Điều đó có nghĩa, nếu bạn đang truy cập một phương thức không đồng bộ tĩnh trong một luồng (thực thi), bạn vẫn có thể truy cập một phương thức được đồng bộ hóa tĩnh bằng cách sử dụng một luồng khác.

Vì vậy, truy cập hai loại phương thức tương tự (hoặc hai phương pháp tĩnh hoặc hai phương pháp không tĩnh) tại bất kỳ thời điểm nào bằng nhiều hơn một chuỗi không thể thực hiện được.

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