Java同步功能工作,同步块不起作用

时间:2015-08-28 07:42:32

标签: java multithreading synchronization synchronized

takeAmount和addAmount只是从balanceAccount添加/ sub值(例如,添加11,12 ...,20或添加101,102 ...,110)。 balanceAccount有两个版本,一个是使用synchronized函数,另一个是使用synchronized块。

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);
    }

}

3 个答案:

答案 0 :(得分:2)

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

另请注意,Integer是不可变的,每次将值重新分配到amount时,您创建的新实例都会丢失您之前的值上的任何锁定。

答案 1 :(得分:0)

您的打印方法定义为

public synchronized static void printAmount()

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

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

答案 2 :(得分:0)

您可以使用

锁定使用调用此方法的对象
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;
        }
    }