【问题标题】:Synchronized method not working as expected同步方法未按预期工作
【发布时间】:2018-05-23 11:43:06
【问题描述】:

我的 java 代码中的方法不应由两个线程同时执行。

package runnableThread;
public class CompteEnBanque {
      private int solde = 100;

      public int getSolde(){
        if(this.solde < 0)
          System.out.println(solde);

        return this.solde;
      }

      public synchronized void retraitArgent(int retrait){
        solde = solde - retrait; 
        System.out.println("Solde = " + solde);                 
      }
    }

package runnableThread;
public class RunImpl implements Runnable {
  private CompteEnBanque cb;
  private String name;

  public RunImpl(CompteEnBanque cb, String name){
    this.cb = cb;
    this.name = name;
  }

  public void run() {
    for(int i = 0; i < 50; i++){
      if(cb.getSolde() >= 2){
        cb.retraitArgent(2);
        System.out.println("Retrait effectué par " + this.name);                       
      }                       
    }               
  } 
}

这是我的 main()

package runnableThread;
public class Test {
      public static void main(String[] args) {
        CompteEnBanque cb = new CompteEnBanque();

        Thread t = new Thread(new RunImpl(cb, "marie"));
        Thread t2 = new Thread(new RunImpl(cb, "philippe"));
        t.start();
        t2.start();
      }
    }

通常情况下,余额(在我的源代码中已售出)永远不会是负数,但是,当我执行此代码时,我会得到负值。我不明白同步是否运作良好。

这里有一些输出

Retrait effectué par marie
Solde = 0
Retrait effectué par marie
Solde = -2
Retrait effectué par philippe
-2

【问题讨论】:

  • 对您号码当前值的检查在您的同步方法之外。这允许另一个线程在完成检查的点和进入同步方法的点之间更新数字。
  • 一切实际上都按预期工作:因为solde 永远不会同步,所以不能保证一个线程看到另一个线程更改的值,或者另一个线程可以在其他线程更改它之前读取该值,但在另一个线程完成修改后会进入同步块。您正在错误的地方寻找错误:测试 synchronized 关键字的工作原理(以及一般的 Java 内存模型)是如此广泛,以至于您误用它比在那里遇到大问题要普遍得多。

标签: java multithreading synchronized


【解决方案1】:

您正在读取同步块之外的焊接值。

要读取正确的值,您需要更新以“发生在”读取它之前。只有当写入和读取都在同一个对象上同步的块内时,才能保证这一点。

同样在 Run 中,if 语句周围没有同步,因此在检查值 >=2 和递减值之间,solde 可能发生了变化。

【讨论】:

    猜你喜欢
    • 2014-03-10
    • 2020-08-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-17
    • 1970-01-01
    • 1970-01-01
    • 2019-04-22
    相关资源
    最近更新 更多