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