it-swarm-vi.tech

Làm thế nào để các phương thức tĩnh được đồng bộ hóa hoạt động trong Java?

Nếu tôi có một lớp tiện dụng với các phương thức tĩnh sẽ gọi các 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 thức synchronized là cách tiếp cận phù hợp để đảm bảo an toàn luồng.

Tôi muốn điều này ngăn chặn truy cập thông tin vào cùng một thể hiện DB. Tuy nhiên, bây giờ tôi chắc chắn nếu đoạn mã sau đang ngă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
}
170
tomato

Bằng cách sử dụng đồng bộ hóa trên khóa phương thức tĩnh, bạn sẽ đồng bộ hóa các phương thức và thuộc tính lớp (trái ngược với các phương thức và thuộc tính thể hiện)

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

Tôi tự hỏi liệu làm cho phương thức được đồng bộ hóa có phải là phương pháp phù hợp để đảm bảo an toàn cho luồng hay không.

Không hẳn vậy. Bạn nên để công việc đó làm RDBMS của bạn thay vào đó. Họ giỏi loại công cụ 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 chậm khủng khiếp. Hơn nữa, trong mã bạn đã đăng bạn đang xây dựng 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 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 bản ghi X của bảng T.

Với cách tiếp cận của bạn, điều duy nhất bạn nhận được là đảm bảo người này được gọi sau người kia, khi điều này xảy ra dù sao trong DB, bởi vì RDBMS sẽ ngă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 hơn).

Có lẽ sẽ tốt hơn nếu xem qua "Giao dịch và đồng thời" chương 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à cách tốt hơn nhiều.

134
OscarRyz

Để giải quyết câu hỏi nói chung hơn ...

Hãy nhớ rằng việc sử dụng đồng bộ hóa trên các phương thức thực sự chỉ là tốc ký (giả sử lớp là someClass):

synchronized static void foo() {
    ...
}

giống như

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

synchronized void foo() {
    ...
}

giống như

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

Bạn có thể sử dụng bất kỳ đối tượng như khóa. Nếu bạn muốn khóa các tập con của phương thức 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) {...}
    }
}

(đối với các phương thức không tĩnh, bạn sẽ muốn làm cho các khóa là các trường không tĩnh)

221
Scott Stanchfield

Các phương thức 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.

17
starblue

static synchronized có nghĩa là giữ khóa trên đối tượng Class của lớp trong đó như synchronized có nghĩa là giữ khóa trên chính đối tượng của lớp đó. Điều đó có nghĩa là, nếu bạn đang truy cập một phương thức được đồng bộ hóa 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, việc truy cập hai loại phương thức giống nhau (hai phương thức tĩnh hoặc hai phương thức không tĩnh) tại bất kỳ thời điểm nào nhiều hơn một luồng là không thể.

14
prasad

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

Đây là công việc của trình điều khiển cơ sở dữ liệ để 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 luồng tại một thời điểm!

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

9
oxbow_lakes

Nếu đó là một cái gì đó để làm với dữ liệu trong cơ sở dữ liệu của bạn, tại sao không sử dụng khóa cách ly cơ sở dữ liệu để đạt được?

2
Ray Lu

Để trả lời câu hỏi của bạn, đúng vậy: phương thức synchronized của bạn không thể được thực thi bởi nhiều hơn một luồng cùng một lúc.

2
David Z