Search in sources :

Example 81 with RLock

use of org.redisson.api.RLock in project redisson by redisson.

the class RedissonFairLockTest method testFirstThreadDeathTimeoutDrift.

@Test
public void testFirstThreadDeathTimeoutDrift() throws Exception {
    int leaseTimeSeconds = 30;
    RLock lock = redisson.getFairLock("test-fair-lock");
    AtomicBoolean lastThreadTryingToLock = new AtomicBoolean(false);
    // create a scenario where the same 3 threads keep on trying to get a lock
    // to exacerbate the problem, use a very short wait time and a long lease time
    // this will end up setting the queue timeout score to a value far away in the future
    ExecutorService executor = Executors.newFixedThreadPool(3);
    for (int i = 0; i < 10; i++) {
        final int finalI = i;
        executor.submit(() -> {
            log.info("running " + finalI + " in thread " + Thread.currentThread().getId());
            try {
                if (lock.tryLock(3000, leaseTimeSeconds * 1000, TimeUnit.MILLISECONDS)) {
                    log.info("Lock taken by thread " + Thread.currentThread().getId());
                    Thread.sleep(100);
                    try {
                        // this could fail before use sleep for the same value as the lock expiry, that's fine
                        // for the purpose of this test
                        lock.unlock();
                        log.info("Lock released by thread " + Thread.currentThread().getId());
                    } catch (Exception ignored) {
                    }
                }
            } catch (InterruptedException ex) {
                log.warn("Interrupted " + Thread.currentThread().getId());
            } catch (Exception ex) {
                log.error(ex.getMessage(), ex);
            }
        });
        // attempting to lock do so in a staggered pattern. This delay will be carried over by the thread pool.
        if (i < 3) {
            Thread.sleep(50);
        }
    }
    // we now launch one more thread and kill it before it manages to fail and clean up
    // that thread will end up with a timeout that will prevent any others from taking the lock for a long time
    executor.submit(() -> {
        log.info("Final thread trying to take the lock with thread id: " + Thread.currentThread().getId());
        try {
            lastThreadTryingToLock.set(true);
            if (lock.tryLock(30000, 30000, TimeUnit.MILLISECONDS)) {
                log.info("Lock taken by final thread " + Thread.currentThread().getId());
                Thread.sleep(1000);
                lock.unlock();
                log.info("Lock released by final thread " + Thread.currentThread().getId());
            }
        } catch (InterruptedException ex) {
            log.warn("Interrupted " + Thread.currentThread().getId());
        } catch (Exception ex) {
            log.error(ex.getMessage(), ex);
        }
    });
    // now we wait for all others threads to stop trying, and only the last thread is running
    while (!lastThreadTryingToLock.get()) {
        Thread.sleep(100);
    }
    // try to kill that last thread, and don't let it clean up after itself
    executor.shutdownNow();
    // force the lock to unlock just in case
    try {
        lock.forceUnlock();
    } catch (Exception e) {
        log.error(e.getMessage(), e);
    }
    if (lock.isLocked()) {
        Assertions.fail("Lock should have been unlocked by now");
    }
    // check the timeout scores - they should all be within a reasonable amount of time from now
    List<Long> queue = redisson.getScript(LongCodec.INSTANCE).eval(RScript.Mode.READ_ONLY, "local result = {}; " + "local timeouts = redis.call('zrange', KEYS[1], 0, 99, 'WITHSCORES'); " + "for i=1,#timeouts,2 do " + "table.insert(result, timeouts[i+1]); " + "end; " + "return result; ", RScript.ReturnType.MULTI, Collections.singletonList("redisson_lock_timeout:{test-fair-lock}"));
    for (int i = 0; i < queue.size(); i++) {
        long timeout = queue.get(i);
        long epiry = ((timeout - new Date().getTime()) / 1000);
        log.info("Item " + i + " expires in " + epiry + " seconds");
        // the Redisson library uses this 60000*5ms delay in the code
        Assertions.assertFalse(epiry > leaseTimeSeconds + 60 * 5 * (i + 1), "It would take more than " + (leaseTimeSeconds + 60 * 5 * (i + 1)) + "s to get the lock!");
    }
}
Also used : AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) RLock(org.redisson.api.RLock) Date(java.util.Date) Test(org.junit.jupiter.api.Test)

Example 82 with RLock

use of org.redisson.api.RLock in project redisson by redisson.

the class RedissonFairLockTest method testIsLockedOtherThread.

@Test
public void testIsLockedOtherThread() throws InterruptedException {
    RLock lock = redisson.getFairLock("lock");
    lock.lock();
    Thread t = new Thread() {

        public void run() {
            RLock lock = redisson.getFairLock("lock");
            Assertions.assertTrue(lock.isLocked());
        }
    };
    t.start();
    t.join();
    lock.unlock();
    Thread t2 = new Thread() {

        public void run() {
            RLock lock = redisson.getFairLock("lock");
            Assertions.assertFalse(lock.isLocked());
        }
    };
    t2.start();
    t2.join();
}
Also used : RLock(org.redisson.api.RLock) Test(org.junit.jupiter.api.Test)

Example 83 with RLock

use of org.redisson.api.RLock in project redisson by redisson.

the class RedissonLockTest method testSubscriptionsPerConnection.

@Test
public void testSubscriptionsPerConnection() throws InterruptedException, IOException {
    RedisRunner.RedisProcess runner = new RedisRunner().port(RedisRunner.findFreePort()).nosave().randomDir().run();
    Config config = new Config();
    config.useSingleServer().setSubscriptionConnectionPoolSize(1).setSubscriptionConnectionMinimumIdleSize(1).setSubscriptionsPerConnection(1).setAddress(runner.getRedisServerAddressAndPort());
    RedissonClient redisson = Redisson.create(config);
    ExecutorService e = Executors.newFixedThreadPool(32);
    AtomicInteger errors = new AtomicInteger();
    AtomicInteger ops = new AtomicInteger();
    for (int i = 0; i < 5000; i++) {
        int j = i;
        e.submit(() -> {
            try {
                String lockKey = "lock-" + ThreadLocalRandom.current().nextInt(5);
                RLock lock = redisson.getLock(lockKey);
                lock.lock();
                Thread.sleep(ThreadLocalRandom.current().nextInt(20));
                lock.unlock();
                ops.incrementAndGet();
            } catch (Exception exception) {
                exception.printStackTrace();
                if (exception instanceof RedisTimeoutException) {
                    return;
                }
                errors.incrementAndGet();
            }
        });
    }
    e.shutdown();
    assertThat(e.awaitTermination(150, TimeUnit.SECONDS)).isTrue();
    assertThat(errors.get()).isZero();
    RedisClientConfig cc = new RedisClientConfig();
    cc.setAddress(runner.getRedisServerAddressAndPort());
    RedisClient c = RedisClient.create(cc);
    RedisConnection ccc = c.connect();
    List<String> channels = ccc.sync(RedisCommands.PUBSUB_CHANNELS);
    assertThat(channels).isEmpty();
    c.shutdown();
    redisson.shutdown();
    runner.stop();
}
Also used : Config(org.redisson.config.Config) IOException(java.io.IOException) RedissonClient(org.redisson.api.RedissonClient) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) RLock(org.redisson.api.RLock) Test(org.junit.jupiter.api.Test)

Example 84 with RLock

use of org.redisson.api.RLock in project redisson by redisson.

the class RedissonLockTest method testLockIsNotRenewedAfterInterruptedTryLock.

@Test
public void testLockIsNotRenewedAfterInterruptedTryLock() throws InterruptedException {
    final CountDownLatch countDownLatch = new CountDownLatch(1);
    RLock lock = redisson.getLock("myLock");
    assertThat(lock.isLocked()).isFalse();
    Thread thread = new Thread(() -> {
        countDownLatch.countDown();
        if (!lock.tryLock()) {
            return;
        }
        lock.unlock();
    });
    thread.start();
    countDownLatch.await();
    // let the tcp request be sent out
    TimeUnit.MILLISECONDS.sleep(5);
    thread.interrupt();
    TimeUnit.SECONDS.sleep(45);
    assertThat(lock.isLocked()).isFalse();
}
Also used : RLock(org.redisson.api.RLock) Test(org.junit.jupiter.api.Test)

Example 85 with RLock

use of org.redisson.api.RLock in project redisson by redisson.

the class RedissonLockTest method testRedisFailed.

@Test
public void testRedisFailed() {
    Assertions.assertThrows(WriteRedisConnectionException.class, () -> {
        RedisRunner.RedisProcess master = new RedisRunner().port(6377).nosave().randomDir().run();
        Config config = new Config();
        config.useSingleServer().setAddress("redis://127.0.0.1:6377");
        RedissonClient redisson = Redisson.create(config);
        RLock lock = redisson.getLock("myLock");
        // kill RedisServer while main thread is sleeping.
        master.stop();
        Thread.sleep(3000);
        lock.tryLock(5, 10, TimeUnit.SECONDS);
    });
}
Also used : RedissonClient(org.redisson.api.RedissonClient) Config(org.redisson.config.Config) RLock(org.redisson.api.RLock) Test(org.junit.jupiter.api.Test)

Aggregations

RLock (org.redisson.api.RLock)113 Test (org.junit.jupiter.api.Test)77 RedissonClient (org.redisson.api.RedissonClient)21 RReadWriteLock (org.redisson.api.RReadWriteLock)18 AtomicInteger (java.util.concurrent.atomic.AtomicInteger)13 RedisProcess (org.redisson.RedisRunner.RedisProcess)12 AtomicBoolean (java.util.concurrent.atomic.AtomicBoolean)11 CacheLoaderException (javax.cache.integration.CacheLoaderException)10 CacheWriterException (javax.cache.integration.CacheWriterException)10 EntryProcessorException (javax.cache.processor.EntryProcessorException)10 Config (org.redisson.config.Config)10 ExecutorService (java.util.concurrent.ExecutorService)8 Test (org.junit.Test)6 RedissonObject (org.redisson.RedissonObject)4 RSemaphore (org.redisson.api.RSemaphore)4 SecureRandom (java.security.SecureRandom)3 Date (java.util.Date)3 Random (java.util.Random)3 CountDownLatch (java.util.concurrent.CountDownLatch)3 Lock (java.util.concurrent.locks.Lock)3