如何在多线程JAVA环境中保护对象而又不损失性能?

亚历克斯

遗留代码如下:

private static final ReentrantLock RE_ENTRANT_LOCK = new ReentrantLock(true);

private void newRunTransaction(final OrderPayment payment, final Address billingAddress, final String command)  {

    TransactionResponse response = null;
    RE_ENTRANT_LOCK.lock();
    try {
        SoapServerPortType client = getClient();
....

我们认为方法开头的锁定是过大的,因为我们应该能够在多个线程中运行事务。另一方面,如果OrderPayment与2个并行线程中的同一订单相关,则我们无法并行运行事务。

是否有任何优雅而有效的方法来确保与一个订单相关的事务不会并行运行,而所有其他事务都是多线程的?

弗洛

[更新]:添加了使用WeakHashMap-Cache的解决方案,以清理垃圾收集器要使用的未使用的锁。它们是在这里开发的:迭代WeakHashMap

如果付款引用了其订单,并且相等的订单是相同的对象(order1 == order2 <=> order1与order2相同),则可以使用同步块:

synchronized(payment.getOrder()) {
    try  {
       // ...
    }
}

警告:您应该确保payment.getOrder()不会产生空值,或者在这种情况下不使用虚拟对象。

编辑:如果order1 == order2不成立,则可能的解决方案:

您可以尝试为订单的相同标识符持有唯一锁:

static Map<Long, Object> lockCache = new ConcurrentHashMap<>();

并在方法中

Object lock = new Object();
Object oldlock = lockCache.putIfAbsent(payment.getOrder().getUid(), lock);
if (oldlock != null) {
    lock = oldlock;
}

synchronized(lock) {
    // ...
}

完成工作后,请不要忘记删除密钥。

要使用垃圾回收来删除未使用的键,可以使用WeakHashMap结构:

private static Map<Long, Reference<Long>> lockCache = new WeakHashMap<>();

public static Object getLock(Longi)
{
    Long monitor = null;
    synchronized(lockCache) {
        Reference<Long> old = lockCache.get(i);
        if (old != null)
            monitor = old.get();

        // if no monitor exists yet
        if (monitor == null) {
            /* clone i for avoiding strong references 
               to the map's key besides the Object returend 
               by this method.
            */ 
            monitor = new Long(i);
            lockCache.remove(monitor); //just to be sure
            lockCache.put(monitor, new WeakReference<>(monitor));
        }

    }

    return monitor;
}

当您需要更复杂的东西(例如可重入锁)时,可以使用以下解决方案的一种变体:

private static Map<Long, Reference<ReentrantLock>> lockCache = new WeakHashMap<>();
private static Map<ReentrantLock, Long> keyCache = new WeakHashMap<>();

public static ReentrantLock getLock(Long i)
{
    ReentrantLock lock = null;
    synchronized(lockCache) {
        Reference<ReentrantLock> old = lockCache.get(i);
        if (old != null)
            lock = old.get();

        // if no lock exists or got cleared from keyCache already but not from lockCache yet
        if (lock == null || !keyCache.containsKey(lock)) {
            /* clone i for avoiding strong references 
               to the map's key besides the Object returend 
               by this method.
           */ 
            Long cacheKey = new Long(i); 
            lock = new ReentrantLock();
            lockCache.remove(cacheKey); // just to be sure
            lockCache.put(cacheKey, new WeakReference<>(lock));
            keyCache.put(lock, cacheKey);
        }                
    }

    return lock;
}

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

如何在ImageView中从相机放映中获取图像而又不损失其在Android中的质量?

来自分类Dev

如何在Ubuntu上将视频缩放到3.5:1而又不损失质量?

来自分类Dev

如何在Java多线程环境中复制ArrayList <T>?

来自分类Dev

Java多线程性能

来自分类Dev

如何在C ++中返回对象而又不会超出范围?

来自分类Dev

如何在C ++中返回对象而又不会超出范围?

来自分类Dev

(Java多线程)如何在多线程中传递参数?

来自分类Dev

如何在整个应用程序中使用PHP类,而又不影响过多的开销性能

来自分类Dev

Java多线程性能改进

来自分类Dev

如何在多线程环境中更好地使用ExecutorService?

来自分类Dev

多线程如何在Web环境中工作

来自分类Dev

c-如何在多线程环境中处理SIGPIPE?

来自分类Dev

如何在多线程环境中正确使用EasyNetQ

来自分类Dev

如何在多线程环境中使用Servlet

来自分类Dev

多线程如何在Web环境中工作

来自分类Dev

如何在多线程环境中使用序列

来自分类Dev

如何保护可能在多线程或异步环境中使用的资源?

来自分类Dev

在多线程环境中用原子保护两个变量

来自分类Dev

如何在多线程C ++程序中删除对象

来自分类Dev

如何在Java中保护敏感数据

来自分类Dev

如何在Java中保护敏感数据

来自分类Dev

如何在Anaconda中将python 2.7.8升级到2.7.9,而又不与环境中的其他组件冲突?

来自分类Dev

如何在多线程环境中使构建器模式线程安全?

来自分类Dev

如何提高多线程 python 程序的性能?

来自分类Dev

如何在多线程Java中插入数据库

来自分类Dev

如何在 Java 中使用多线程和 ArrayList

来自分类Dev

python多线程性能

来自分类Dev

多线程:映射性能

来自分类Dev

随着线程池大小的增加,Java多线程性能最差

Related 相关文章

  1. 1

    如何在ImageView中从相机放映中获取图像而又不损失其在Android中的质量?

  2. 2

    如何在Ubuntu上将视频缩放到3.5:1而又不损失质量?

  3. 3

    如何在Java多线程环境中复制ArrayList <T>?

  4. 4

    Java多线程性能

  5. 5

    如何在C ++中返回对象而又不会超出范围?

  6. 6

    如何在C ++中返回对象而又不会超出范围?

  7. 7

    (Java多线程)如何在多线程中传递参数?

  8. 8

    如何在整个应用程序中使用PHP类,而又不影响过多的开销性能

  9. 9

    Java多线程性能改进

  10. 10

    如何在多线程环境中更好地使用ExecutorService?

  11. 11

    多线程如何在Web环境中工作

  12. 12

    c-如何在多线程环境中处理SIGPIPE?

  13. 13

    如何在多线程环境中正确使用EasyNetQ

  14. 14

    如何在多线程环境中使用Servlet

  15. 15

    多线程如何在Web环境中工作

  16. 16

    如何在多线程环境中使用序列

  17. 17

    如何保护可能在多线程或异步环境中使用的资源?

  18. 18

    在多线程环境中用原子保护两个变量

  19. 19

    如何在多线程C ++程序中删除对象

  20. 20

    如何在Java中保护敏感数据

  21. 21

    如何在Java中保护敏感数据

  22. 22

    如何在Anaconda中将python 2.7.8升级到2.7.9,而又不与环境中的其他组件冲突?

  23. 23

    如何在多线程环境中使构建器模式线程安全?

  24. 24

    如何提高多线程 python 程序的性能?

  25. 25

    如何在多线程Java中插入数据库

  26. 26

    如何在 Java 中使用多线程和 ArrayList

  27. 27

    python多线程性能

  28. 28

    多线程:映射性能

  29. 29

    随着线程池大小的增加,Java多线程性能最差

热门标签

归档