java - 为什么除非我使用 .join(),否则同步方法不会被锁定?

标签 java concurrency synchronized

Java中,将方法标记为同步应该禁用由于两个线程调用正在访问和修改的方法而导致的竞争条件同一对象中的字段。

但由于某种原因,除非我在主程序中的两个线程上调用 .join(),否则 synchronized 在以下示例中无法按预期工作。这是为什么?

package example;

public class Account {
    private double balance;

    public Account(double balance) {
        super();
        this.balance = balance;
    }

    public synchronized void deposit(double amount) {
        balance += amount;
    }

    public double getBalance() {
        return balance;
    }
}
package example;

public class AccountTester extends Thread {
    private Account account;
    private double amount;

    public AccountTester(Account account, double amount) {
        this.account = account;
        this.amount = amount;
    }

    public static void main(String[] args) {
        Account account = new Account(0);
        AccountTester tester1 = new AccountTester(account, 1.0);
        AccountTester tester2 = new AccountTester(account, 2.0);
        tester1.start();
        tester2.start();
        // Why do I need the main thread to join threads
        //      tester1 and tester2 for synchronized to work?
        try {
            tester1.join();
            tester2.join();
        } catch (InterruptedException e) {
            System.err.println(e);
        }
        System.out.println("End balance: " + account.getBalance());
    }

    @Override
    public void run() {
        for (int i = 0; i < 1000; i++) {
            account.deposit(amount);
        }
    }
}

最佳答案

正如@flakes所澄清的,代码需要主线程join()两个线程来保证两个线程都终止,即在打印出之前完成对余额的修改结束余额

实现此目的的更简洁的方法是使用 java.util.concurrent.ExecutorService 接口(interface)。这里其 shutdown() 方法保证线程池中的两个线程在打印最终余额之前完成。这是我的实现:

package example;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class AccountTester implements Runnable {
    private Account account;
    private double amount;

    public AccountTester(Account account, double amount) {
        this.account = account;
        this.amount = amount;
    }

    public static void main(String[] args) {
        Account account = new Account(0);
        ExecutorService executorService = Executors.newFixedThreadPool(2);
        executorService.execute(new AccountTester(account, 1.0));
        executorService.execute(new AccountTester(account, 2.0));
        executorService.shutdown();
        System.out.println("End balance: " + account.getBalance());
    }

    @Override
    public void run() {
        for (int i = 0; i < 1000; i++) {
            account.deposit(amount);
        }
    }
}

关于java - 为什么除非我使用 .join(),否则同步方法不会被锁定?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56640820/

相关文章:

java - 同步(对象) { } 问题

java - 测试用例使此代码失败?

java - 如何获取内容://mms-sms/conversations intent in Android?

java - Java多线程并发问题

java - javafixedThreadPool可以被多个线程使用吗

java - 设计并编写一个任务调度程序,可以接受不同步或同步的任务

java - Springboot同步方法

java - 如何从camel路由中的camel上下文获取属性值

java - 找不到 Android R.anim.files

java - 主 Java 线程终止时如何管理工作线程生命周期?