使用 ReentrantLock 而不是 synchronized 来提高性能
Using ReentrantLock instead of synchronized for improving performance
我正在努力寻找适合我的特定情况的最佳解决方案。
我目前有以下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
}
}
}
class代表一个用户组分享的金额的所有更新。该组最多可包含 100 个用户。 amount
字段可以由组中的任何用户同时更新。
调用 update(int)
包括输入两个同步块,从性能的角度来看这不是很好。也可能会发生 BULK 操作将被计算两次或更多次,即使不需要它。实际上,假设三个线程正试图同时访问 update()
。 check(date)
在每个线程中返回 true。它没有任何危害,但是 BULK 操作非常繁重(多于 1 分钟)。所以,如果没有必要,不要执行两次是很重要的。
无法将 BULK 操作包装到同步块中,因为它包括调用几个外来方法。所以,我倾向于使用 ReentrantLock
而不是同步。 class 可以改写如下:
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
更有效。
你可以在没有同步的情况下做同样的事情。
仅当线程需要知道变量的值以更新它时才需要同步。如果线程仅更改一个变量,则将其定义为 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
}
}
注意: 如果金额取决于实际金额值,则可能需要进行同步。不需要同步日期
我正在努力寻找适合我的特定情况的最佳解决方案。
我目前有以下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
}
}
}
class代表一个用户组分享的金额的所有更新。该组最多可包含 100 个用户。 amount
字段可以由组中的任何用户同时更新。
调用 update(int)
包括输入两个同步块,从性能的角度来看这不是很好。也可能会发生 BULK 操作将被计算两次或更多次,即使不需要它。实际上,假设三个线程正试图同时访问 update()
。 check(date)
在每个线程中返回 true。它没有任何危害,但是 BULK 操作非常繁重(多于 1 分钟)。所以,如果没有必要,不要执行两次是很重要的。
无法将 BULK 操作包装到同步块中,因为它包括调用几个外来方法。所以,我倾向于使用 ReentrantLock
而不是同步。 class 可以改写如下:
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
更有效。
你可以在没有同步的情况下做同样的事情。
仅当线程需要知道变量的值以更新它时才需要同步。如果线程仅更改一个变量,则将其定义为 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
}
}
注意: 如果金额取决于实际金额值,则可能需要进行同步。不需要同步日期