JAVA多线程-对象锁

每个对象都共享一把synchronized

我们看下例子,我们个人应该都会去银行开个账户,账户有名称和账户余额:

package com.ck.thread;



import java.math.BigDecimal;



package com.ck.thread;



import java.math.BigDecimal;



public class Account {



    private String name;

   

    private BigDecimal balance = new BigDecimal("0");

   



    public String getName() {

        return name;

    }



    public void setName(String name) {

        this.name = name;

    }



    public BigDecimal getBalance() {

        return balance;

    }


    public void setBalance(BigDecimal balance) {

        this.balance = balance;

    }
   

    public synchronized void add(BigDecimal amount) {

        System.out.println(name + ", 开始充值,充值前余额: " + balance);

        try {

            Thread.sleep(2000);

            balance = balance.add(amount);

        } catch (InterruptedException e) {

            e.printStackTrace();

        }

        System.out.println(name + ", 结束充值,充值后余额: " + balance);

    }

   

    public  void print() {

        System.out.println(name + ", 当前余额: " + balance);



    }

}

我们在写个充值的线程类:

package com.ck.thread;

import java.math.BigDecimal;



public class CzThread extends Thread{

    private Account account;
   

    public CzThread(Account account) {

        this.account = account;

    }
   

    @Override

    public void run() {

        account.add(new BigDecimal("100"));

    }


    public Account getAccount() {

        return account;

    }


    public void setAccount(Account account) {

        this.account = account;

    }


}

再写个查询余额的线程:

package com.ck.thread;


public class PrintThread extends Thread{


    private Account account;


    public PrintThread(Account account) {

        this.account = account;

    }

   

    @Override

    public void run() {

        account.print();

    }


    public Account getAccount() {

        return account;

    }


    public void setAccount(Account account) {

        this.account = account;

    }


}

然后用户先充值,在查询余额:

package com.ck.thread;

import java.math.BigDecimal;


public class MainThread {


    public static void main(String[] args) throws InterruptedException {

        Account account1 = new Account();

        account1.setName("张三");

        account1.setBalance(new BigDecimal("100"));

       

        Thread t1 = new CzThread(account1);

        t1.start();

        Thread.sleep(500);

        Thread t2 = new PrintThread(account1);

        t2.start();

    }


}

我们看下结果:


张三, 开始充值,充值前余额: 100

张三, 当前余额: 100

张三, 结束充值,充值后余额: 200

这时候用户就会找银行了 我明明充值了100为什么还是显示余额100,为了解决这个问题我们把用户账户类稍微修改下:

package com.ck.thread;

import java.math.BigDecimal;

public class Account {


    private String name;


    private BigDecimal balance = new BigDecimal("0");


    public String getName() {

        return name;

    }



    public void setName(String name) {

        this.name = name;

    }



    public BigDecimal getBalance() {

        return balance;

    }


    public void setBalance(BigDecimal balance) {

        this.balance = balance;

    }

   

    public synchronized void add(BigDecimal amount) {

        System.out.println(name + ", 开始充值,充值前余额: " + balance);


        try {

            Thread.sleep(2000);

          balance = balance.add(amount);

        } catch (InterruptedException e) {

            e.printStackTrace();

        }

        System.out.println(name + ", 结束充值,充值后余额: " + balance);

    }

    /**注意这儿加锁了*/

    public synchronized void print() {

        System.out.println(name + ", 当前余额: " + balance);



    }

}

我们再看下执行结果:

 

张三, 开始充值,充值前余额: 100

张三, 结束充值,充值后余额: 200

张三, 当前余额: 200

这下就正确了,这是为什么呢?

这是synchronized作用的范围是该对象,如果该对象的方法加上synchronized那么就会同步,否则就会出现刚开始余额不正确的情况。

猜你喜欢

转载自blog.csdn.net/cgsyck/article/details/105915156