5 线程同步
取钱的例子:OOP 编程实现
1. 从需求中提取名词
wife husband 余额 取款金额 账户
2. 从静态、动态两个层面描述名词
wife 静态:有一个账号 动态:取钱的行为 (方法调用)
husband 静态:有一个账号 动态:取钱的行为 (方法调用)
账户: 静态:账户的余额 动态: 取钱的行为 存钱的行为 (方法定义)
3. 是否可以合并名词 -- 类
Person类
Account类
建议: !!先做被依赖的!!
4. 实现业务逻辑
版本一: 模拟先后取钱
h,w均持有账号可以取钱。假设银行卡内有3000元,h和w每人一次取2000.
public class Test {
public static void main(String[] args) {
Account account = new Account(3000);
Person h = new Person(account);
Person w = new Person(account);
h.quqian("husband");
w.quqian("wife");
}
}
class Person {
private Account account;
public Person(Account account) {
this.account = account;
}
public void quqian(String user) {
account.withdraw(user,2000);
}
}
class Account {
private int balance;
public Account(int balance) {
this.balance = balance;
}
public void withdraw(String user,int money) {
if (balance>=money) {
System.out.println(user+"取了"+money+"元");
balance -= money;
} else {
System.out.println(user+"余额不足!");
}
System.out.println(user+"你的余额是:"+balance+"元");
}
}
版本二:h和w同时取钱----线程
public class Test {
public static void main(String[] args) {
Account account = new Account(3000);
//两个线程类访问同一个共享资源
Person h = new Person(account);
Person p = new Person(account);
h.start();
w.start();
}
}
class Person extends Thread {
private Account account;
public Person() {
}
public void run() {
account.withdraw(2000);
}
}
class Account {
private int balance;
public Acccount(int balance) {
this.balance = balance;
}
public void withdraw(int money) {
if (balance>=money) {
System.out.println(Thread.currentThread().getName()+"取了"+money+"元");
try {
Thread.sleep(1000);
} catch (Exception e) {
e.printStackTrace();
}
balance -= money;
} else {
System.out.println("余额不足");
}
System.out.println("余额为"+balance);
}
}
多个线程同时访问同一个共享资源时,出错
错误原因:当一个线程访问(纯粹的“查询/破坏性操作--填删改”)共享资源时,被另一个线程打断了
解决思路:当一个线程访问共享资源结束,别的线程不允许访问该共享资源
解决方案:synchronized关键字,把访问共享资源的代码括起来
具体实现有两种书写格式:
1.
public void withdraw(int money) {
synchronized(this) {
//访问共享资源的代码段
}
}
2.
public synchronized void withdraw() {
}
当一个线程执行了synchronized修饰的代码块或者方法,当该代码段或者该方法执行完之前,那么该代码块或者该方法所属的那个对象就被当前线程“绑定”,直到执行完
版本三:
public class Test {
public static void main(String[] args) {
Account account = new Account(3000);
Person h = new Person(account);
Person p = new Person(account);
h.start();
w.start();
}
}
class Person extends Thread {
private Account account;
public Person(Account account) {
this.account = account;
}
public void run() {
account.withdraw(2000);
}
}
class Account {
private int balance;
public Acccount(int balance) {
this.balance = balance;
}
public void withdraw(int money) {
synchronized (this) {
//this变量 就是调用withdraw()方法的那个对象--->account--->
if (balance>=money) {
System.out.println(Thread.currentThread().getName()+"取了"+money+"元");
try {
Thread.sleep(1000);
} catch (Exception e) {
e.printStackTrace();
}
balance -= money;
} else {
System.out.println("余额不足");
}
System.out.println("余额为"+balance);
}
}
}