【问题标题】:Java synchronized function work while synchronized block not work [duplicate]Java同步功能工作,而同步块不起作用[重复]
【发布时间】:2015-08-28 07:42:31
【问题描述】:

takeAmount 和 addAmount 只是从 balanceAccount 中添加/子值(例如添加 11,12...,20 或添加 101,102...,110)。 balanceAccount 有两个版本,一个是使用同步功能,另一个是使用同步块。

BalanceAccount_synchronizedBlock 和 BalanceAccount_synchronizedFunction 有什么不同吗?

确实 BalanceAccount_synchronizedFunction 总是返回 0,而 BalanceAccount_synchronizedBlock 则不会。

而且...为什么它会表现出不同的行为?

public class mainStart {
    public static void main(String args[]) 
    {
        for (int i=1;i<3000;i=i+10)
        {
            new Thread(new addAmount(i)).start();
            new Thread(new takeAmount(i)).start();
        }

        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //BalanceAccount_synchronizedBlock.printAmount();
        BalanceAccount_synchronizedFunction.printAmount();
    }


}

class takeAmount implements Runnable {
    private int startFrom;

    public takeAmount(int start)
    {
        this.startFrom=start;
    }

    public void run() 
    {   
        for (int i=startFrom;i<startFrom+10;i++)
            //BalanceAccount_synchronizedBlock.sub(i);
            BalanceAccount_synchronizedFunction.sub(i);
    }

}

class addAmount implements Runnable {
    private int startFrom;

    public addAmount(int start)
    {
        this.startFrom=start;
    }

    public void run() 
    {   
        for (int i=startFrom;i<startFrom+10;i++)
            //BalanceAccount_synchronizedBlock.add(i);
            BalanceAccount_synchronizedFunction.add(i);
    }

}

public class BalanceAccount_synchronizedBlock {
    public static Integer amount=0;

    public static void add(int a)
    {
        synchronized (amount)
        {
            amount = amount + a;
        }
    }

    public static void sub(int a)
    {
        synchronized (amount)
        {
            amount = amount - a;
        }
    }

    public synchronized static void printAmount()
    {
        System.out.println("Amount " + amount);
    }

}

public class BalanceAccount_synchronizedFunction {
    public static Integer amount=0;

    public synchronized static void add(int a)
    {
            amount = amount + a;
    }

    public synchronized static void sub(int a)
    {
            amount = amount - a;
    }

    public synchronized static void printAmount()
    {
        System.out.println("Amount " + amount);
    }

}

【问题讨论】:

  • 它表现出什么不同的行为?
  • 不要在Integer 上同步,因为它是不可变的,当amount 被替换时,您将在不同的对象上同步,这可能会导致一些有趣的问题。您可以改用Object lock = new Object(); 进行同步。
  • 感谢您的回复。它工作。

标签: java multithreading synchronization synchronized


【解决方案1】:

同步方法使用封闭类作为同步标记。当您编写synchronized(amount) 时,您正在使用Integer 实例作为同步令牌。由于您在两种情况下都没有使用相同的令牌,因此锁定不会按预期发生。

另请注意,Integer 是不可变的,每次您将值重新分配给 amount 时,您都在创建一个新实例,并失去您对先前值的任何锁定。

【讨论】:

    【解决方案2】:

    您的打印方法定义为

    public synchronized static void printAmount()
    

    在类本身上同步。在您的“块”尝试的情况下,块在amount 上同步,而 print 方法在类上同步。更改该方法以使用在 amount 上也同步的块。

    正如 Kayaman 指出的那样,您还遇到了一个问题,即您正在同步一个变量 (amount),其所指对象不断变化。相反,声明一个仅用于同步的private static final Object LOCK = new Object()——或者更好的是,只使用AtomicInteger

    【讨论】:

    • 感谢您的回复,我尝试了您的建议,它有效。
    【解决方案3】:

    您可以使用调用此方法的对象锁定

    synchronized (this) { // this is similar to method level synchronization
    

    或者使用其他类级别的对象而不是数量整数(正如 @Kayaman 指出的那样,它是不可变的,因此每次更新它时都会创建新的整数对象)

    public class BalanceAccount_synchronizedBlock {
        public static Integer amount=0;
        public static Object Lock = new Object();
    
        public static void add(int a) {
            synchronized (Lock) {
                amount = amount + a;
            }
        }
    

    【讨论】:

      猜你喜欢
      • 2013-08-04
      • 1970-01-01
      • 2022-01-13
      • 2010-09-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-03-30
      • 1970-01-01
      相关资源
      最近更新 更多