同步2种方法

时间:2015-09-22 11:19:53

标签: java multithreading synchronized java.util.concurrent

public class ActionForm {
       private Account temporaryAccount = null;
       private Document document;

       /**
       * Save document from another thread that do not have a SecurityContext
       */
       public void saveByAccount(Account account) { 
           this.temporaryAccount = account;
           save();
           this.temporaryAccount = null;
       }

       /**
       * Save document to DB. 
       * I can not change the signature of this method.
       */
       public synchronized void save() {

          //get an account from shared variable or from SecurityContext
           Account account = null;
           Account temporaryAccount = this.temporaryAccount;
           if (temporaryAccount == null) {
               account = SecurityContextWrapper.getAccount();
           } else {
               account = temporaryAccount;
           }

        //save in DB
        saveDocumentInDB(account, document);
    }
}

线程类型1 :用户可以点击按钮"保存",在这种情况下,方法save()将直接调用。我从SecurityContext获得帐户。

线程类型2 :用户启动后台进程。我保存他/她的帐户,然后开始新的帖子:

final Account account = SecurityContextWrapper.getAccount();
new Thread(new Runnable() {
    public void run() {
        ...//do smth
        saveByAccount(account);
    }
}).start();

问题:可以更改变量 this.temporaryAccount - 在调用saveByAccount()和save()之间。 你知道同步这些方法的正确方法吗?

1 个答案:

答案 0 :(得分:0)

解决此问题的最佳方法是将帐户作为参数发送到每个方法。封装总是一个很好的功能,你应该尽可能地努力。这样,当你需要进行参数化时,你就不会遇到这种麻烦。

鉴于您的评论不能更改方法签名,我建议您在开始使用共享变量之前使用信号量。

您可以使用以下代码在类级别创建信号量:

private final Semaphore available = new Semaphore(1, true);

在尝试更改或使用共享变量之前,每个方法都必须调用available.acquire();。如果信号量正在使用中,这将阻止(因为你有一个许可证,如构造函数调用中所定义的),但是如果它是空闲的,那么它会将许可证数量减少一个并继续。

完成依赖共享变量的处理后,每个方法都应调用available.release();。然后,等待服务的其他方法之一将获得信号量并继续。

尽管如此,我强烈建议您花时间重构代码。全局变量和类变量是“代码味道”,并且可能在将来引发错误。花在这个重构上的时间会对未来感兴趣。这类讨论可以在诸如“代码完整”和“清洁代码”等优秀书籍中找到。它们必须读取并为我们,程序员提供有关代码质量的大量见解。

我希望这会有所帮助。