Mallikarjun Vishwanath
Mallikarjun Vishwanath

Reputation: 103

Deadlock issue with Striped.lock()

I'm using Stripe.lock() from com.google.guava.guava-28.0-jre.jar

public class NamedLock {
    private static final Logger LOGGER = Logger.getLogger(NamedLock.class);

    private Striped<Lock>       locks;

    public NamedLock() {
        locks = Striped.lock(1023);
    }

    /**
     * Test method
     * 
     * @param args
     * @throws InterruptedException
     */
    public static void main(String[] args) throws InterruptedException {
        NamedLock namedLock = new NamedLock();
        Runnable runnable = () -> {
            namedLock.lock("aAp1h0000004oEcCAI");
            try {
                TimeUnit.SECONDS.sleep(5);
            } catch (Exception e) {
                e.printStackTrace();
            }
            namedLock.lock("aAT1h0000001OzCGAU");
        };
        new Thread(runnable).start();
        TimeUnit.SECONDS.sleep(2);
        namedLock.lock("aAp1h0000004oFRCAY");
        namedLock.lock("aAp1h0000004oKYCAY");

    }

    /**
     * Acquires the lock for the Names.
     * 
     * @param names
     *            the Names
     */
    public void lock(String... names) {
        String key = Arrays.toString(names);
        LOGGER.debug("Locking with Key : " + key);
        Lock lock = locks.get(key);
        LOGGER.debug("Acquiring Lock : " + lock);
        lock.lock();
        LOGGER.debug("Lock acquired : " + lock);
    }

    /**
     * Releases the lock acquired for the Names.
     * 
     * @param names
     *            the Names
     */
    public void unlock(String... names) {
        String key = Arrays.toString(names);
        LOGGER.debug("Unlocking with Key : " + key);
        Lock lock = locks.get(key);
        LOGGER.debug("Releasing Lock : " + lock);
        lock.unlock();
        LOGGER.debug("Lock released : " + lock);
    }

}

Result for the program :

| DEBUG | 2019-08-13 14:58:33.973 | Thread-0 | NamedLock:61 | Locking with Key : [aAp1h0000004oEcCAI]
| DEBUG | 2019-08-13 14:58:33.975 | Thread-0 | NamedLock:63 | Acquiring Lock : com.google.common.util.concurrent.Striped$PaddedLock@ac92ce3[Unlocked]
| DEBUG | 2019-08-13 14:58:33.975 | Thread-0 | NamedLock:65 | Lock acquired : com.google.common.util.concurrent.Striped$PaddedLock@ac92ce3[Locked by thread Thread-0]
| DEBUG | 2019-08-13 14:58:35.973 | main | NamedLock:61 | Locking with Key : [aAp1h0000004oFRCAY]
| DEBUG | 2019-08-13 14:58:35.974 | main | NamedLock:63 | Acquiring Lock : com.google.common.util.concurrent.Striped$PaddedLock@574caa3f[Unlocked]
| DEBUG | 2019-08-13 14:58:35.980 | main | NamedLock:65 | Lock acquired : com.google.common.util.concurrent.Striped$PaddedLock@574caa3f[Locked by thread main]
| DEBUG | 2019-08-13 14:58:35.981 | main | NamedLock:61 | Locking with Key : [aAp1h0000004oKYCAY]
| DEBUG | 2019-08-13 14:58:35.982 | main | NamedLock:63 | Acquiring Lock : com.google.common.util.concurrent.Striped$PaddedLock@ac92ce3[Locked by thread Thread-0]
| DEBUG | 2019-08-13 14:58:38.976 | Thread-0 | NamedLock:61 | Locking with Key : [aAT1h0000001OzCGAU]
| DEBUG | 2019-08-13 14:58:38.982 | Thread-0 | NamedLock:63 | Acquiring Lock : com.google.common.util.concurrent.Striped$PaddedLock@574caa3f[Locked by thread main]

The program never terminates and goes into DeadLock state, waiting for each others lock though all the keys are different.

Upvotes: 1

Views: 522

Answers (1)

Michael
Michael

Reputation: 44200

From the JavaDoc:

Note that if key1 is not equal to key2, it is not guaranteed that striped.get(key1) != striped.get(key2)

So presumably more than one of your keys exists in the same stripe. The hash codes are relatively close together for some of them so it seems reasonable:

System.out.println("[aAp1h0000004oEcCAI]".hashCode()); // -1286359401
System.out.println("[aAp1h0000004oFRCAY]".hashCode()); // -1273429611
System.out.println("[aAp1h0000004oKYCAY]".hashCode()); // -1123819209
System.out.println("[aAT1h0000001OzCGAU]".hashCode()); //  1694776185

It sounds like Striped is not applicable to your use-case and that you need one lock per object.

Upvotes: 2

Related Questions