每个对象都共享一把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那么就会同步,否则就会出现刚开始余额不正确的情况。