如何对String值进行重入锁定?

时间:2017-08-27 12:37:53

标签: java multithreading reentrantlock

我有一个多线程应用程序,我想在String上使用重入锁定。例如,如果我使用普通同步,我的代码看起来就像。

我不希望两个相同IP地址的线程进入我的loadBalance(),所以我锁定IP地址,这是正常工作。

class A {
    String ipAddress;
    ...
    void loadBalance() {
        synchronized (ipAddress) {
            // Business logic goes here
        }
    }
}

现在如果我在这里使用可重入的API,那么代码将如下所示。现在我的代码中输入了两个相同IP地址的线程,这是不需要的。所以我需要知道如何使用重入API来防止这种情况。

class A {
    String ipAddress;
    ReentrantLock lock = new ReentrantLock();
    ...
    void loadBalance() {
        lock.lock();
            // Business logic goes here
        lock.unlock();
    }
}

我的查询是如何使用Re-entrant锁定IP地址,就像我在synchronized block中所做的那样。

2 个答案:

答案 0 :(得分:2)

不是每个String都有一个锁,这可能会导致锁的数量不断增加,最终可能是OutOfMemoryError,在这种情况下最好使用条带锁定策略。

制作有限数量的锁(假设n),将它们存储在一个数组中。如果您需要锁定给定的String,请使用其hashCode()和模n来确定哪个数组元素包含要使用的锁。等于String s将使用相同的锁。

private static final int N = 10;
private ReentrantLock[] locks = new ReentrantLocks[N];

{
    for (int i = 0; i < N; i++) {
        locks[i] = new ReentrantLock();
    }
}

...

// where you need a lock :
String ipAddress = ...

ReentrantLock lock = locks[ipAddress.hashCode() % N];
lock.lock();

权衡是一些不相等的String s也将使用相同的锁。您应该使用不同数量的n进行测试,以在不需要的锁争用和内存之间取得平衡。

或者你可以使用Guava的Striped

答案 1 :(得分:0)

我找到了一种方法,但不确定这个方法是否正确。 我找到了一个class,它会对提供的String名称提供锁定

import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.ReentrantLock;

public class LockByName<L> {

    ConcurrentHashMap<String, L> mapStringLock;

    public LockByName() {
        mapStringLock = new ConcurrentHashMap<String, L>();
    }

    public LockByName(ConcurrentHashMap<String, L> mapStringLock) {
        this.mapStringLock = mapStringLock;
    }

    @SuppressWarnings("unchecked")
    public L getLock(String key) {
        L initValue = (L) createIntanceLock();
        L lock = mapStringLock.putIfAbsent(key, initValue);
        if (lock == null) {
            lock = initValue;
        }
        return lock;
    }

    protected Object createIntanceLock() {
        return new ReentrantLock();
    }

}

class A {
String ipAddressl
    LockByName<ReentrantLock> reentrantLocker = new LockByName<ReentrantLock>();
    ...
    ReentrantLock reentrantLock1 = reentrantLocker.getLock(ipAddress);

    try {
        reentrantLock1.lock();
        // DO WORK

    } finally {
        reentrantLock1.unlock();

    }

}
相关问题