2013-04-22 38 views
13

Theo Java Concurrency in Practice, chương 11.4.3 nói:Cần lời giải thích đơn giản như thế nào "khóa vằn" làm việc với ConcurrentHashMap

Khóa tách đôi khi có thể được mở rộng để phân vùng khóa trên một tập variablesized của các đối tượng độc lập , trong trường hợp này là , nó được gọi là khóa dải. Ví dụ, việc thực hiện ConcurrentHashMap sử dụng một mảng gồm 16 khóa, mỗi khóa bảo vệ 1/16 của các nhóm băm; xô N được bảo vệ bởi khóa N mod 16.

Tôi vẫn có vấn đề để hiểu và hình dung cơ chế khóa và ngăn chặn khóa. Ai đó có thể giải thích điều này với những từ hiểu biết tốt :)

Xin cảm ơn trước.

Trả lời

30

Bản đồ băm được xây dựng trên một mảng, trong đó hàm băm ánh xạ một đối tượng thành một phần tử trong mảng cơ bản. Giả sử mảng cơ bản có 1024 phần tử - ConcurrentHashMap thực sự biến mảng này thành 16 mảng phụ khác nhau của 64 phần tử, ví dụ: {0, 63}, {64, 127}, v.v. Mỗi mảng phụ có khóa riêng, do đó việc sửa đổi mảng phụ {0, 63} không ảnh hưởng đến mảng phụ {64, 127} - một chuỗi có thể ghi vào mảng con đầu tiên trong khi một luồng khác ghi vào mảng phụ thứ hai.

+0

OK, tôi hiểu. Nhưng còn nếu hai hoặc nhiều luồng đang cố sửa đổi tất cả trong mảng phụ {0,63} thì sao? – GedankenNebel

+3

Sau đó, nó đến trước được phục vụ trước tiên - luồng đầu tiên để lấy khóa làm thay đổi của nó, sau đó khi nó kết thúc luồng thứ hai làm thay đổi. 'ConcurrentHashMap' có các phương thức như' replace' để đảm bảo rằng luồng thứ hai không vô tình ghi đè lên các thay đổi của luồng đầu tiên. –

+0

Tôi không nghĩ rằng nó thực sự là "đầu tiên đến trước được phục vụ", như tôi đã hiểu (tôi không có báo giá chính xác, nhưng tôi đã học được từ Java Concurrency in Practice), sự công bằng chỉ được đảm bảo khi nó rõ ràng, như trong các nhà xây dựng để triển khai 'Lock' khác nhau rõ ràng, chẳng hạn như' ReentrantLock' hoặc Hàng đợi như 'ArrayBlockingQueue'. (Tôi biết đó là một chủ đề cũ, xin lỗi) – Marcelo

11

Sự khác biệt giữa khóa trong một Collections.synchronizedMap() và một ConcurrentHashMap là như sau:

Nếu có nhiều chủ đề sẽ truy cập vào một Collections.synchronizedMap() thường xuyên, sẽ có rất nhiều tranh cãi vì mỗi phương pháp được đồng bộ bằng một khóa chia sẻ (ví dụ: nếu thread X gọi phương thức trên Collections.synchronizedMap(), tất cả các chủ đề khác sẽ bị chặn gọi bất kỳ phương thức nào trên Collections.synchronizedMap() cho đến khi chuỗi X trả về từ phương thức được gọi).

A ConcurrentHashMap có số lượng khóa thay đổi (mặc định là 16) mà mỗi khóa bảo vệ một đoạn khóa trong ConcurrentHashMap. Vì vậy, đối với một ConcurrentHashMap với 160 phím, mỗi khóa sẽ bảo vệ 10 phần tử. Do đó, các phương thức hoạt động trên một khóa (get, put, set, v.v.) chỉ khóa quyền truy cập vào các phương thức khác hoạt động trên khóa mà các phím nằm trong cùng một phân đoạn. Ví dụ: nếu chuỗi X gọi put(0, someObject) và sau đó, chuỗi Y gọi put(10, someOtherObject) các cuộc gọi đó có thể thực thi đồng thời và chuỗi Y không phải chờ chuỗi X trở về từ put(0, someObject). Một ví dụ được cung cấp dưới đây.

Ngoài ra, một số phương pháp nhất định như size()isEmpty() không được bảo vệ. Mặc dù điều này cho phép đồng thời nhiều hơn, điều đó có nghĩa là chúng không nhất quán (chúng sẽ không phản ánh trạng thái đồng thời thay đổi).

public static void main(String[] args) { 
    ConcurrentHashMap<Integer, Object> map = new ConcurrentHashMap<>(160); 

    new Thread(new Runnable() { 
    @Override 
    public void run() { 
     map.put(0, "guarded by one lock"); 
    } 
    }.start(); 

    new Thread(new Runnable() { 
    @Override 
    public void run() { 
     map.put(10, "guarded by another lock"); 
    } 
    }.start(); 

    new Thread(new Runnable() { 
    @Override 
    public void run() { 
     // could print 0, 1, or 2 
     System.out.println(map.count()); 
    } 
    }.start(); 
} 
+0

HashMap trong java không phải là chủ đề an toàn, HashTable là. Kịch bản đầu tiên bạn nói đến là cho HashTable –

2

Khái niệm chính ở đây là "nhóm". thay vì sử dụng khóa toàn cầu cho toàn bộ Bảng băm này, nó sử dụng một khóa nhỏ cho mỗi nhóm. Nó cũng là một tương tự tốt để sắp xếp xô mà có thể cải thiện phân loại phức tạp.

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