2011-09-26 13 views
8

Tôi đang đọc cuốn sách Java Concurrency in Practice. Trong một phần về java.util.concurrent.Semaphore, các dòng dưới đây có trong sách. Đó là một nhận xét về việc thực hiện các "giấy phép ảo" đối tượngLàm thế nào và tại sao một Semaphore có thể đưa ra nhiều giấy phép hơn so với khi nó được khởi tạo?

Việc thực hiện không có đối tượng giấy phép thực tế, và Semaphore không không Associate giấy phép phân phối với chủ đề, do đó, một giấy phép mua lại vào một thread có thể được phát hành từ một chủ đề khác. Bạn có thể nghĩ đến số acquire khi sử dụng giấy phép và release khi tạo một giấy phép; a Semaphore không giới hạn số giấy phép được tạo.

Ai đó có thể giải thích điều này? Tôi gặp khó khăn khi hiểu điều này. Nếu chúng tôi tạo một nhóm có kích thước cố định, chúng tôi sẽ tạo một số "giấy phép" cố định. Từ tuyên bố trên, có vẻ như "giấy phép" có thể tiếp tục phát triển. Tại sao nó được thiết kế theo cách này?

+0

trông giống cụm từ trang trí công phu – gstackoverflow

Trả lời

8

Thay vì "bàn giao" các đối tượng giấy phép, việc triển khai chỉ có bộ đếm. Khi một giấy phép mới được "tạo ra", bộ đếm được tăng lên, khi một giấy phép được trả về, bộ đếm sẽ giảm.

Điều này làm cho hiệu suất tốt hơn nhiều so với việc tạo đối tượng thực tế mọi lúc.

Sự cân bằng là chính Semaphore không thể phát hiện một số loại lỗi lập trình nhất định (chẳng hạn như tiền mặt cho phép trái phép hoặc rò rỉ semaphore). Là người lập trình, bạn phải đảm bảo tuân theo các quy tắc của riêng bạn.

+0

Java có cung cấp một loại semaphore khác thực sự thực thi giới hạn giấy phép không? Tôi chỉ muốn release() trở thành no-op khi tất cả các giấy phép đã được phát hành ... Trong một hệ thống phức tạp với rất nhiều luồng, nó không dễ dàng để đảm bảo rằng mỗi thread luôn luôn mua và giải phóng chính xác một giấy phép . – Dasmowenator

+0

@Dasmowenator: Tôi cho rằng bạn có thể tự mình cuộn lên trên AtomicInteger. Nhưng điều đó không có vẻ giống như một cách tiếp cận tốt. Bạn thực sự nên chắc chắn rằng mã khóa của bạn là chính xác về mặt logic. Nếu bạn thấy cần phải phát hành no-op, điều đó có thể có nghĩa là ai đó đang giải phóng nhiều ổ khóa hơn là họ nên có. Và điều đó sẽ phá vỡ những thứ không thể sửa được bằng cách bỏ qua một số cuộc gọi semaphore. – Thilo

+0

Bạn cũng có thể sử dụng cách "đồng bộ" truyền thống. Ít linh hoạt, nhưng an toàn (không bị rò rỉ, chăm sóc tái nhập vv). – Thilo

5

Ai đó có thể giải thích điều này? Từ tuyên bố trên, có vẻ như "giấy phép" có thể tiếp tục phát triển.

Một semaphore là bộ đếm giấy phép. có được giống như giảm đi mà chờ đợi hơn là đi dưới số không. Nó không có giới hạn trên.

Tại sao thiết bị được thiết kế theo cách này?

Bởi vì nó đơn giản để làm như vậy.

+0

Không giới hạn trên, giới hạn trên sẽ không là số giấy phép? – Scorpion

+0

Giới hạn trên là số lần phát hành trừ đi số lần có được số lần gọi. Bạn có thể gọi phát hành bất kỳ số lần nào. Có một giới hạn trên của Integer.MAX_VALUE trong một số triển khai. –

+0

Vậy làm cách nào để tạo một semaphore vững chắc với tối đa là 1 - bất kể số lần phát hành được gọi là bao nhiêu? – slott

2

Tôi nghĩ rằng nó có nghĩa là thời gian mà chúng tôi có thể yêu cầu Semaphore như thời gian chúng tôi phát hành "bổ sung" và cộng với giấy phép mà nó tạo ra.

Chẳng hạn như:

Semaphore s = new Semaphore(1); // one permit when initialize 

s.acquire(); 
s.release(); 

s.release(); // "extra" release. 

Tại thời điểm này, semaphore này cho phép một giấy phép ban đầu và một "thêm" giấy phép

-1

Có lẽ dòng cuối cùng "một Semaphore không giới hạn số lượng giấy phép nó được tạo ra với "là nguồn gây nhầm lẫn của bạn.

Một semaphore khi được tạo được khởi tạo với một bộ giấy phép cố định. Điều này sau đó trở thành số lượng giấy phép tối đa mà semaphore có thể đồng thời phân phối bất cứ lúc nào trong suốt thời gian cuộc đời của semaphore đó. Bạn không thể tăng động số này trừ khi khởi tạo lại semaphore.Ý nghĩa nếu dòng trích dẫn (từ JCIP) là: Thứ nhất, ngữ nghĩa về cách hoạt động của semaphore không giới hạn chi tiết về việc cấp và lấy lại giấy phép - điều này được thể hiện trong thực tế là bất kỳ chủ đề nào có thể có quyền truy cập semaphore có thể có một giấy phép phát hành (mặc dù thread này không sở hữu giấy phép ở nơi đầu tiên)

Thứ hai, bạn có thể tự động giảm giấy phép tối đa của semaphore - bằng cách gọi phương thức reducePermits(int).

3

Như đã đề cập trong bài viết đầu tiên "Semaphore không giới hạn số lượng giấy phép nó được tạo ra với"

Mỗi cuộc gọi đến .release() API sẽ làm tăng số lượng giấy phép một. Vì vậy, Semaphores không có kích thước giấy phép cố định

+0

bạn có thể giải thích .release() làm việc sau đó không? Vì vậy, nếu tôi tạo ra một đối tượng semaphore với 0 thì không có thread có thể có được giấy phép từ nó? Nhưng nếu tôi gọi .release() trên nó đầu tiên và sau đó .acquire() trong dòng tiếp theo, nó sẽ cho phép một sợi để có được giấy phép? –

1

Điều đáng ngạc nhiên đối với một số người trong chúng ta.

Bạn có thể dễ dàng phân lớp lên một semaphore bị chặn.

/** 
* Terrible performance bounded semaphore. 
**/ 
public class BoundedSemaphore extends Semaphore { 
    private static final long serialVersionUID = -570124236163243243L; 
    final int bound; 
    public BoundedSemaphore(int permits) { 
     super(permits); 
     bound=permits; 
    } 

    @Override 
    synchronized public void acquire() throws InterruptedException { 
     super.acquire(); 
    } 

    @Override 
    synchronized public boolean tryAcquire() { 
     return super.tryAcquire(); 
    } 

    @Override 
    synchronized public void release() { 
     if(availablePermits()<bound){ 
      super.release(); 
     } 
    } 
    @Override 
    synchronized public void acquire(int count) throws InterruptedException { 
     super.acquire(count); 
    } 

    @Override 
    synchronized public boolean tryAcquire(int count) { 
     return super.tryAcquire(count); 
    } 

    @Override 
    synchronized public void release(int count) { 
     if(availablePermits()<bound){ 
      super.release(bound-availablePermits()); 
     } 
    } 
} 
Các vấn đề liên quan