@Test public void testSemaphoreSplitBrain() throws InterruptedException { Config config = newConfig(); HazelcastInstance h1 = Hazelcast.newHazelcastInstance(config); HazelcastInstance h2 = Hazelcast.newHazelcastInstance(config); final HazelcastInstance h3 = Hazelcast.newHazelcastInstance(config); final String key = generateKeyOwnedBy(h3); ISemaphore semaphore = h3.getSemaphore(key); semaphore.init(5); semaphore.acquire(3); assertEquals(2, semaphore.availablePermits()); assertTrueEventually( new AssertTask() { @Override public void run() throws Exception { assertTrue(h3.getPartitionService().isLocalMemberSafe()); } }); TestMemberShipListener memberShipListener = new TestMemberShipListener(2); h3.getCluster().addMembershipListener(memberShipListener); TestLifeCycleListener lifeCycleListener = new TestLifeCycleListener(1); h3.getLifecycleService().addLifecycleListener(lifeCycleListener); closeConnectionBetween(h1, h3); closeConnectionBetween(h2, h3); assertOpenEventually(memberShipListener.latch); assertClusterSizeEventually(2, h1); assertClusterSizeEventually(2, h2); assertClusterSizeEventually(1, h3); final ISemaphore semaphore1 = h1.getSemaphore(key); // when member is down, permits are released. // since releasing the permits is async, we use assert eventually assertTrueEventually( new AssertTask() { @Override public void run() throws Exception { assertEquals(5, semaphore1.availablePermits()); } }); semaphore1.acquire(4); assertOpenEventually(lifeCycleListener.latch); assertClusterSizeEventually(3, h1); assertClusterSizeEventually(3, h2); assertClusterSizeEventually(3, h3); ISemaphore testSemaphore = h3.getSemaphore(key); assertEquals(1, testSemaphore.availablePermits()); }