Hazelcast - ISemaphore



java.util.concurrent.Semaphore 通过在 JVM 的多线程环境中提供有限的访问权限来支持同步。

听起来很像锁,对吧?但是锁和信号量之间有两个主要区别:

  • 信号量没有所有权。它可以被一个线程获取,并由另一个线程释放。锁与线程绑定。它需要由同一个线程释放和获取。

  • 信号量支持根据**req**和可用许可证,允许一个或多个线程进入临界区。

类似地,ISemaphore 提供了 Java Semaphore 的分布式版本。它提供类似的功能:acquire(获取),release(释放)。

但是 ISemaphore 和 Java Semaphore 之间的一个主要区别是:Java Semaphore 提供了对单个 JVM 中线程的临界区的保护,而 ISemaphore 则为单个 JVM 和多个 JVM 中的线程提供同步。

ISemaphore 只有一个同步备份,这意味着,如果我们有一个设置,例如运行 5 个 JVM,则只有两个 JVM 会持有此信号量。

获取许可证,释放许可证

示例

让我们在**三个 JVM**上执行以下代码。该代码应该打印已获取信号量的线程数。我们有 2 个许可证,这意味着一次只允许两个线程进入 if 块。

public static void main(String... args) throws IOException, InterruptedException {
   //initialize hazelcast instance
   HazelcastInstance hazelcast = Hazelcast.newHazelcastInstance();
   // create a lock
   ISemaphore hzSemaphore = hazelcast.getSemaphore("semaphore_1");
   IAtomicLong activeThreads = hazelcast.getAtomicLong("threads");
   hzSemaphore.init(2);
   for(int i=0; i< 10; i++) {
      if(hzSemaphore.tryAcquire(2000, TimeUnit.MILLISECONDS)); {
         System.out.println("Thread count: " +
         activeThreads.incrementAndGet());
         Thread.sleep(2000);
         hzSemaphore.release();
         activeThreads.decrementAndGet();
      }
   }
   System.exit(0);
}

代码的输出显示我们有 1 或 2 个活动线程,这正是我们根据许可证设置为 2 所期望的。

最佳实践

  • 如果拥有许可证的成员宕机,则许可证会自动释放,使其可供其他线程获取。

  • 避免使用信号量的 acquire() 方法,因为它是一个阻塞调用,可能会导致死锁。最好使用带有超时的 tryAcquire() 方法来避免阻塞。

常用方法

序号 函数名称和描述
1

acquire()

如果可用,则获取许可证。如果不可用,它会无限期等待直到许可证可用。

2

release()

释放已获取的许可证。

3

tryAcquire(long time, TimeUnit unit)

尝试在给定的时间窗口内获取许可证。如果获取许可证,则返回 true,否则返回 false。

4

availablePermits()

返回此 ISemaphore 实例可用的许可证数量。

hazelcast_data_structures.htm
广告