Java同步不起作用(I)预期

Lai*_*ira 2 java multithreading synchronization

程序员队友.我用一个非常简单的代码测试java线程功能(或者至少看起来很简单).我有这个班级帐号:

public class Account {
    protected double balance;

    public synchronized void withdraw(double value) {
        this.balance = this.balance - value;
    }

    public synchronized void deposit(double value) {
        this.balance = this.balance + value;
    }

    public synchronized double getBalance() {
        return this.balance;
    }
}
Run Code Online (Sandbox Code Playgroud)

我有两个主题:Depositer一千万次存款10美元:

public class Depositer extends Thread {
    protected Account account;

    public Depositer(Account a) {
        account = a;
    }

    @Override
    public void run() {
        for(int i = 0; i < 1000; i++) {
            this.account.deposit(10);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

而且Withdrawer,这一次提取10万美元:

public class Withdrawer extends Thread {
    protected Account account;

    public Withdrawer(Account a) {
        account = a;
    }

    @Override
    public void run() {
        for(int i = 0; i < 1000; i++) {
            this.account.withdraw(10);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这种安排由以下人员执行:

public class Main {
    public static void main(String[] args) {
        Account account = new Account();
        Thread c1 = new Depositer(account);
        Thread c2 = new Withdrawer(account);

        c2.start();
        c1.start();

        System.out.println(account.getBalance());
    }
}
Run Code Online (Sandbox Code Playgroud)

由于方法是同步的,我只是期望最后的余额总是为0,但有时候不会发生这种情况.我真诚地想不出原因.有人能看出我的错吗?

Eug*_*ota 6

c2.start()c1.start()异步运行的过程.您的主线程需要等待这两个线程完成才能打印出结果.

呼叫

try {
    c2.join();
    c1.join();
} catch (InterruptedException e) {
    e.printStackTrace();
}
Run Code Online (Sandbox Code Playgroud)

在调用println之前.

join.

等待这个线程死亡.


Edd*_*die 5

您执行以下操作:

c2.start();  // Start a thread in the background
c1.start();  // Start a 2nd thread in the background

// print out the balance while both threads are still running
System.out.println(account.getBalance());
Run Code Online (Sandbox Code Playgroud)

您需要等待这些线程完成其处理:

c2.start();  // Start a thread in the background
c1.start();  // Start a 2nd thread in the background

try {
    c2.join();  // Wait until the c2 thread completes
    c1.join();  // Wait until the c1 thread completes
} catch (InterruptedException e) {
    // LOG AN ERROR HERE
}

// print out the final balance
System.out.println(account.getBalance());
Run Code Online (Sandbox Code Playgroud)

如果你打断主线程,那么你需要对中断的异常一些事情.假设您的代码都没有这样做,您应该始终至少记录异常.注意:如果有人中断,或者如果有人打断了您的主线程,则调用的线程将获得InterruptedException not.如果有人打电话给你的主线程,但你没有检查它,那么你可能会在你打电话的那一刻得到它.c1c2join()interrupt()InterruptedExceptionjoin()