【问题标题】:Confused with java synchorized block对 java 同步块感到困惑
【发布时间】:2018-10-09 04:44:20
【问题描述】:

这些天,我正在阅读 Core Java 和 当我阅读并发章节时,我很困惑。有一个同步块的例子,这里是段:


[

我对标注句的理解是,如果Vector的get方法不同步或者我没有劫持'accounts'的锁,这种传输方法就不是线程安全的。

然后我写了一些测试代码。我使用另一个锁而不劫持锁。但结果与我的理解相反。

以下是我的代码。

public class VectorBank {
    public void transfer(Vector<Integer> accounts, int from, int to, Integer amount) {
        synchronized (this) {
            if (accounts.get(from) < amount) return;
            accounts.set(from, accounts.get(from) - amount);
            accounts.set(to, accounts.get(to) + amount);
            System.out.println(getTotalBanlance(accounts));
        }
    }

    public Integer getTotalBanlance(Vector<Integer> accounts) {
        Integer sum = new Integer(0);
        for (Integer a : accounts) {
            sum += a;
        }
        return sum;
    }
}

测试类:

public class VectorBankTest {
    public static final int MAX_AMOUNT = 1000;
    public static final int DELAY = 10;
    public static final int NACCOUNTS = 100;
    public static final int INITIAL_BALANCE = 1000;

    public static void main(String[] args) {
        Vector<Integer> accounts = new Vector<>();
        for (int i = 0; i < NACCOUNTS; i++) {
            accounts.add(INITIAL_BALANCE);
        }
        VectorBank bank = new VectorBank();
        for (int i = 0; i < NACCOUNTS; i++) {
            int fromAccount = i;
            Runnable r = () -> {
                try {
                    while (true) {
                        int toAccount = (int) (accounts.size() * Math.random());
                        int amount = (int) (MAX_AMOUNT * Math.random() + 1);
                        bank.transfer(accounts, fromAccount, toAccount, amount);
                        Thread.sleep((int) (DELAY * Math.random()));
                    }
                } catch (InterruptedException e) {
                    System.out.println("Do nothing!");
                }
            };
            Thread t = new Thread(r);
            t.start();
        }
    }
}

结果让我一头雾水。我成功同步了所有线程,所有帐户的总余额总是100000。


[

所以我的确切问题是,同步块确实可以做什么? “劫持一把锁”的真正含义是什么?

【问题讨论】:

  • 只有一个线程尝试添加多个线程有和没有同步块只有这样同步才有意义
  • 对不起,我听不懂你在说什么。你的意思是一个线程尝试添加多个线程?
  • 我认为你是对的。有时需要“劫持”锁以防止在敏感操作期间进行修改,例如,在迭代时防止 CME。但是这个例子并没有证明这一点。任何共享锁在这里都足够了。
  • 一切都发生在一个锁内,因此您可以单线程处理所有关键代码,将 total 的打印移出锁并移除睡眠。

标签: java concurrency synchronized


【解决方案1】:

我们使用 synchronized 关键字来防止多个线程作用于属于线程作用的同一对象的方法。同步主要用于防止来自线程的结果不一致。同步会延迟其他线程的执行。所以 synchronized 关键字仅用于我们希望一次只执行一个线程的特定方法或代码块。

【讨论】:

  • 我知道这个“同步关键字”的概念,我假设你只是不回答我的问题......
猜你喜欢
  • 2021-07-26
  • 2014-03-29
  • 2015-12-24
  • 2022-01-04
  • 1970-01-01
  • 2018-10-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多