1.为什么要使用线程同步?
为了 “数据”的安全(多个线程共用数据),尽管使用效率会降低,但是数据是安全,所以必须采用同步线程机制,也就是线程同步。
2.多线程编程模型:
异步编程模型:t1线程执行t1的,t2执行t2的,两个线程之间不干扰,谁也不等谁。
同步编程模型:t1线程和t2线程同时执行,t1线程必须等t2线程执行结束之后,t1才能执行,这种叫做线程同步。
3.多线程编程使用条件
1 必须是多线程环境
2 多线程环境下数据共享
3 共享的数据设计到修改的操作
举例子说明同步编程和异步编程有什么优点缺点?关于银行取钱!
先采用异步编程操作同一个数据会有什么后果?
package com.Tread.test;
public class test {public static void main(String[] args) {
//共享对象
DemoTests dt = new DemoTests(5000);
Thread t1 = new Thread(dt);
t1.setName("黎明取钱");
t1.start();
Thread t2 = new Thread(dt);
t2.setName("王名取钱");
t2.start();
}
}
//实体类
class DemoTests implements Runnable{
private int account;//余额
public int getAccount() {
return account;
}
public void setAccount(int account) {
this.account = account;
}
public DemoTests(int account) {
this.account = account;
}
public void accountMoney(int account) {
account = account - 1000;
setAccount(account); //剩余余额
}
@Override
public void run() {
//取钱
accountMoney(account);
System.out.println(Thread.currentThread().getName() + "取钱"+1000 + "剩余金额为:" + this.getAccount() );
}
}
}
两条线程互不干涉,这里多运行几次就会发现有什么问题。
运行结果如下:
第一次成功
第二次失败(建议运行多次看看效果)
第三次成功
这样子每次运行的结果不一样,安生活中例子来说,去一次银行就应该操作一次,自己账户中就应该减少一次金额。
但是在第二次情况中两个人对同一个账户取钱两次,余额还是3000这样是存在问题的!
所以这种情况下我们应该采取同步线程编程操作!
所以我们采用关键字“”synchronized“”对其进行加锁,限制让多个线程同时访问这段代码,也就是对这个数据进行操作。
也可以采用方法上加锁(这样子做的对此方法中所有代码进行加锁保护,缺点是此方法中万一其他代码不需要同步,所以推荐采用上面那种,代码片段加锁。)
这段代码意思是
把需要同步的代码,放到同步语句块中。
原理:t1线程和t2线程。
t1线程执行到此,遇到synchronized关键字,就会去找this的对象锁。
如果找到this对象锁,则进入同步语句块中执行程序。当同步语句块中的代码执行结束后,t1归还this的对象锁。
t2执行时候发现T1线程正在执行(t1对象在使用this的对象锁,但是对象锁被t1线程所持有,只能等t1归还后才能执行)。
最后多次运行后结果仍是下面图例所示: