信号量如何以及为什么可以发出比初始化时更多的许可?

发布于 2024-12-06 16:08:04 字数 404 浏览 1 评论 0原文

我正在阅读《Java 并发实践》一书。在关于 java.util.concurrent.Semaphore 的部分中,书中出现了以下几行。这是对其实施“虚拟许可”对象的评论

该实现没有实际的许可对象,而 Semaphore 有 不将分配的许可与线程关联起来,因此在 一个线程可以从另一个线程中释放。你可以想到 获取作为消耗许可,释放作为创建许可;一个 Semaphore 不受其创建时所使用的许可数量的限制。

有人可以解释一下吗?我很难理解这一点。如果我们创建一个固定大小的池,我们就会创建固定数量的“许可证”。从上面的说法来看,“许可证”似乎还可以继续增长。为什么要这样设计呢?

I am reading the book Java Concurrency in Practice. In a section about java.util.concurrent.Semaphore, the below lines are present in the book. It is a comment about its implementation of "virtual permit" objects

The implementation has no actual permit objects, and Semaphore does
not associate dispensed permits with threads, so a permit acquired in
one thread can be released from another thread. You can think of
acquire as consuming a permit and release as creating one; a
Semaphore is not limited to the number of permits it was created with.

Can somebody explain this? I am having trouble understanding this. If we create a pool of fixed size, we create a fixed number of "permits". From the above statement, it looks like the "permits" can keep growing. Why is it designed this way?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

空城之時有危險 2024-12-13 16:08:04

该实现没有“分发”许可对象,而是只有一个计数器。当“创建”新许可证时,计数器增加,当“返回”许可证时,计数器减少。

这比一直创建实际对象具有更好的性能。

代价是信号量本身无法检测某些类型的编程错误(例如未经授权的许可兑现或信号量泄漏)。作为编码员,您必须确保自己遵守规则。

Instead of "handing out" permit objects, the implementation just has a counter. When a new permit is "created" the counter is increased, when a permit is "returned" the counter is decreased.

This makes for much better performance than creating actual objects all the time.

The tradeoff is that the Semaphore itself cannot detect certain kinds of programming errors (such as unauthorized permit cash-ins, or semaphore leaks). As the coder, you have to make sure to follow the rules on your own.

终遇你 2024-12-13 16:08:04

有人可以解释一下吗?从上面的说法来看,“许可证”似乎还可以继续增长。

信号量是许可证计数器。 acquire 就像减量一样,它会等待而不是低于零。它没有上限。

为什么要这样设计?

因为这样做很简单。

Can somebody explain this ? From the above statement, it looks like the "permits" can keep growing.

A semaphore is a counter of permits. acquire is like decrement which waits rather than go below zero. It has no upper limit.

Why is it designed this way ?

Because its simple to do so.

新人笑 2024-12-13 16:08:04

我认为这意味着我们可能需要信号量的时间,即我们释放“额外”的时间以及它所创建的许可证的时间。

如:

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

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

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

此时该信号量本来允许一个许可,又允许一个“额外”许可

I think that it means the times what we may require Semaphore as the times we released "extra" and plus the permits it created with.

Such as:

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

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

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

At this moment, this semaphore allows one permit originally and one "extra" permit

檐上三寸雪 2024-12-13 16:08:04

正如第一篇文章中提到的“信号量不限于创建它所用的许可数量

每次调用 .release() API 都会将许可计数增加 1。所以信号量没有固定的许可大小

As mentioned in first post "Semaphore is not limited to the number of permits it was created with"

Every call to .release() API will increase the permit count by one. So Semaphores doesn't have a fixed permit size

无人接听 2024-12-13 16:08:04

也许最后一行“信号量不限于创建它所用的许可证数量”是您困惑的根源。

信号量在创建时使用一组固定的许可进行初始化。然后,这将成为该信号量在该信号量的生命周期内的任何时间可以同时分配的最大许可数。除了重新初始化信号量之外,您无法动态增加此数字。

引用的行(来自 JCIP)的含义是这样的:首先,信号量如何工作的语义不限于发出和重新获得许可的细节 - 这体现在任何线程都可以访问信号量的事实中。可以释放许可证(即使该线程一开始并不拥有许可证)

其次,您可以动态减少信号量的最大许可证 - 通过调用reducePermits(int) 方法。

Perhaps the last line " a Semaphore is not limited to the number of permits it was created with" is your source of confusion.

A semaphore when created is initialized with a fixed set of permits. This then becomes the maximum number of permits that the semaphore can simultaneuosly dispense at any time during the life time of that semaphore. You cannot dynamically increase this number except by re-initializing the semaphore .

The meaning if the quoted line ( from JCIP ) is this : First , the semantics of how a semaphore works is not limited to the details of issuing and regaining a permit - this is manifested in the fact that any thread can that has access the semaphore can have a permit released ( even though this thread did not own the permit at the first place)

Second , you can dynamically reduce the maximum permits of a semaphore - by calling reducePermits(int) method.

千里故人稀 2024-12-13 16:08:04

这让我们中的一些人感到惊讶。

您可以轻松地对有界信号量进行子类化。

/**
 * 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());
        }
    }
}

It is surprising to some of us.

You can easily subclass up a bounded semaphore.

/**
 * 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());
        }
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文