使用ReentrantLock而不是synchronized来提高性能

时间:2015-11-13 09:49:13

标签: java multithreading synchronization locking

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

我目前有以下课程:

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)包括输入两个同步块,从性能角度来看这不是很好。此外,即使不需要BULK操作也可以计算两次或更多次。实际上,假设三个线程同时尝试访问update()check(date)在每个线程中返回true。它不会造成任何伤害,但 BULK 操作非常重(超过1分钟)。因此,如果没有必要,即使两次也不执行它至关重要。

无法将 BULK 操作包装到同步块中,因为它包括调用几个外来方法。所以,我倾向于使用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之内的情况下synchronization使用{{1}}是否更有效。

1 个答案:

答案 0 :(得分:1)

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

仅当线程需要知道变量的值才能更新它时,才需要进行同步。如果线程只更改变量,则将其定义为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
    }
}

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