
t1和t2
异步编程模型:t1线程执行t1的,t2线程执行t2的
同步编程模型:t1线程和t2线程执行,当t1线程必须等t2线程执行以后,t1线程才能执行
什么时候要同步那?为什么要引入线程同步那?
1、为了数据的安全,暂时不考虑效率。
线程同步机制使程序变成了(等同)单线程
2、什么条件下要使用线程同步?
第一:必须是多线程环境
第二:多线程共享同一个数据
第三:共享的数据涉及到修改操作
栗子:
一下程序演示取款的栗子,不使用线程同步机制,多线程同时堆同一个账户进行取款操作,会出现什么问题?
测试类:
class Test {
public static void main(String[] args){
// 创建一个公共的账户
Account1 act = new Account1("hl", 5000.0);
// 创建线程对同一账户取款
Porcessor p = new Porcessor(act);
Thread t1 = new Thread(p);
Thread t2 = new Thread(p);
t1.start();
t2.start();
}
}
抽象线程
class Porcessor implements Runnable{
// 账户
Account1 act;
Porcessor(Account1 act) {
this.act = act;
};
@Override
public void run() {
// TODO Auto-generated method stub
act.withdraw(1000.0);
System.out.println("取款成功1000,余额" + act.getBalance());
}
}
账户
class Account1{
private String actno;
private double balance;
public Account1() {}
public Account1(String actno,double balance) {
this.actno = actno;
this.balance = balance;
}
public String getActno() {
return actno;
}
public void setActno(String actno) {
this.actno = actno;
}
public double getBalance() {
return balance;
}
public void setBalance(double balance) {
this.balance = balance;
}
public void withdraw(double money) {
double after = balance - money;
// 延迟
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// 更新
this.setBalance(after);
}
}
输出:
取款成功1000,余额4000.0
取款成功1000,余额4000.0
这是发现了异步的问题。
详解synchronized(对象锁)
第一种:
public void withdraw(double money) {
// 把同步代码放在同步语句块中
/*
原理:t1线程和t2线程
t1线程执行到此地,遇到了synchronized关键字,就会去找this的对象锁,
如果找到this对象锁,则进入同步语句块中执行程序,当同步语句块中的代码结束后,t1线程归还this的对象锁
在t1线程执行同步语句块的过程中,如果t2线程也过来执行一下代码,也遇到synchronized关键字,所以也去找this的对象锁,
但是该对象被t1线程持有,只能在这等待this对象的归还。
* */
synchronized(this) {
double after = balance - money;
// 延迟
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// 更新
this.setBalance(after);
}
}
}
输出:
取款成功1000,余额4000.0
取款成功1000,余额3000.0
第二种:
// synchronized关键字添加成员方法上,线程拿走的也是this的对象锁
public synchronized void withdraw(double money) {
double after = balance - money;
// 延迟
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// 更新
this.setBalance(after);
}
}
我们发现第一种方法更加精细。
网友评论