[英]How to make method thread safe, even I forget to add synchronization on method or block level without changing file?
在一位知名公司的面试中,我收到了如下问题:
你有一个类,你的同事忘记同步一些重要的方法,你如何在不改变同一个类的情况下使它线程安全?
public class Account{
//some variables
public boolean withdraw()
{
//some business logic
return true;
}
public boolean deposite()
{
//some business logic
return false;
}
}
我不确定答案是什么,这也可能是愚蠢的答案。 请帮我得到答案。
我的回答:我给出的答案就像我们可以对其进行包装并且我们可以同步。 这不是令人信服的答案,我认为这是获得答案的最佳平台
我在这里看到两个可能的答案:
public class SyncrhonizedAccess extends Account {
public synchronized boolean withdraw() {
return super.withdraw();
}
public synchronized boolean deposite() {
return super.deposite();
}
}
public class AccountWrapper {
private final Account realAcount;
public AccountWrapper(Account realAccount) {
this.realAccount = realAccount;
}
public synchronized boolean withdraw()
{
return realAccount.withdraw();
}
public synchronized boolean deposite()
{
return realAccount.deposite();
}
}
现在这两种方法都可以通过多种方式完成(像我展示的那样手动),自动生成(归结为上述方法之一,只是由像 CGLIB(字节代码生成库)这样的库“自动”完成),或者甚至使用 AOP(面向方面的编程)。
另一个注意事项是,可以在方法内部创建一个锁并对其进行同步,而不是使用单词synchronized
。
当然,如果Account
类具有共享状态,那么这一切都是有意义的 - 数据字段实际上被withdraw
和deposite
方法更改和访问。 否则你真的不需要同步任何东西。
我肯定会使用一个方面并同步对方法的调用。 我会选择这个选项,因为我的应用程序或第三方库的其他点正在调用这些方法
代码示例:
@Aspect
public class AspectAccount {
private static final Object lock = new Object();
@Pointcut("execution(* path.to.package.Account.*(..) )")
public void callAt() {
}
@Around("callAt()")
public Object around(ProceedingJoinPoint pjp) throws Throwable {
synchronized (lock) {
return pjp.proceed();
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.