java - 使用ReentrantLock代替synchronized来提高性能

标签 java multithreading synchronization locking

我正在尝试为我的特定情况找到最佳解决方案。

我目前有以下类(class):

public class Container

    private volatile Date date;
    private int amount;
    private final Object lock = new Object();

    public void update(int amount){
        int actualAmount;
        if(check(date)){
              //do some BULK computation to compute the actualAmount
             synchronized(lock){
                 date = new Date();
                 this.amount = actualAmount;
             }
        }
    }

    private boolean check(Date date){
        synchronized(lock){
          //reading from the date and returning true if the date is expired
        }
    }
}

该类代表用户组共享的金额的所有更新。该组最多可包含 100 名用户。 amount 字段可以由组中的任何用户同时更新。

调用update(int)包括输入两个同步块(synchronized block),从性能角度来看这不是很好。此外,即使不需要,BULK 操作也可能会被计算两次或更多次。实际上,假设三个线程尝试同时访问update()check(date) 在每个线程中返回 true。它不会造成任何损害,但BULK操作相当繁重(超过1分钟)。因此,如果没有必要,不要执行两次,这一点至关重要。

不可能将BULK操作包装到同步块(synchronized block)中,因为它包含调用几个外来方法。因此,我倾向于使用 ReentrantLock 而不是同步。然后该类可以重写如下:

public class Container

    private volatile Date date;
    private int amount;
    private final Lock lock = new ReentrantLock();

    public void update(int amount){
        int actualAmount;
        lock.lock();
        try{
            if(check(date)){
                 //do some BULK computation to compute the actualAmount
                 date = new Date();
                 this.amount = actualAmount;
            }
        } finally {
            lock.unlock();
        }
    }

    private boolean check(Date date){
         //reading from the date and returning true if the date is expired
    }
}

问题:在这种情况下使用ReentrantLock是否比显式同步更有效。

最佳答案

您可以在不同步的情况下执行相同的操作。

仅当线程需要知道变量的值来更新它时才需要同步。如果线程只更改一个变量,则将其定义为 volatile 就足够了。

public class Container

    private volatile Date date;
    private volatile int amount;

    public void update(int amount){
        int actualAmount;
        if (check(date)) {
              //do some BULK computation to compute the actualAmount

             date = new Date();
             this.amount = actualAmount;
        }
    }

    private boolean check(Date date) {

          //reading from the date and returning true if the date is expired
    }
}

注意:如果金额取决于实际金额值,则可能需要同步。不需要同步日期

关于java - 使用ReentrantLock代替synchronized来提高性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33689850/

相关文章:

c++ - winsock2线程安全吗?

java - 我应该如何设计这个程序?

Java ConcurrentSkipListMap : adding atomically another Collection object

java - 正则表达式匹配帮助

java - GAE - JPA - datanucleus 数据检索错误 - PESSIMISTIC_READ

java - 更新后无法再运行 jdbc

java - Java 线程单元测试

multithreading - Lua - 如何模拟 "multithreading"?

javascript - requireJS 模块的同步方法调用

multithreading - 如何正确实现三重缓冲?