1、运行结果不惟一,取决于线程调度
2、线程执行被打断时出现错误
3、线程互斥和临界区管理:操作系统对共享一个变量的若干线程进入各自临界区有以下3个调度原则:
1) 一次至多一个线程能够在它的临界区内。
2) 不能让一个线程无限地留在它的临界区内。
3) 不能强迫一个线程无限地等待进入它的临界区。特别地,进入临界区的任一线程不能妨碍正等待进入的其他线程的进展。
4、Java的线程互斥实现:
1) 同步语句
synchronized (对象)
语句
2) 同步方法
synchronized 方法声明
5、互斥的存/取款线程设计
Account:
package thread3.bank3; public class Account { private String name; //储户姓名 private double balance; //账户余额 //开户 public Account(String name){ this.name = name; this.balance=0; } public String getName(){ return name; } //查看余额 public double balance(){ return balance; } //存款 public void put( double value){ if(value>0){ this.balance +=value; } } //取款: 如果余额不够就把剩余金额全部取出,如果余额足够则可取value public double get( double value){ if(value>0){ if(value <=balance){//存款够取 this.balance -=value; }else{ value = this.balance; this.balance = 0; } return value; } return 0; } synchronized public void fetchWork(double value){ // 先看看有多少钱 double howmuch = balance; // 模拟用户的操作时间差 try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } // 取款 double v = get(value); // 再看看还剩多少 double remain = balance; // 信息输出 System.out.println(name + "账户:现有" + howmuch + ",取出" + v + ",余额" + remain); } synchronized public void saveWork(double value){ // 先看看账户中有多少钱 double howmuch = balance; // 模拟用户的操作时间差 try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } // 存钱 put(value); // 再看看账户余额,以确认钱已经存进去了 double b = balance; // 信息输出 System.out.println(name+ "账户:现有" + howmuch + ",存入" + value + ",余额" + b); } } class Fetch extends Thread { private double value;// 取款金额 private Account account;// 取款账户 public Fetch(Account account, double value) { this.account = account; this.value = value; } @Override public void run() { this.account.fetchWork( this.value ); } } class Save extends Thread { private double value;// 存款金额 private Account account;// 存款账户 public Save(Account account, double value) { this.account = account; this.value = value; } public void run() { account.saveWork(value); } }Bank:
package thread3.bank3; public class Bank { public static void main(String[] args) { //用同步方法: synchrozized public void aa() { ...... } //方法aa()的调用对象就是对象锁 Account li = new Account("Li"); Account wang = new Account("Wang"); Save s1 = new Save(wang,100); Save s2 = new Save(wang,200); Save s5 = new Save(wang,300); Save s4 = new Save(wang,200); Fetch f1 = new Fetch(wang,300); Save s3 = new Save(li,100); s3.start(); s2.start(); s1.start(); s4.start(); s5.start(); f1.start(); } }正确结果:
错误结果://错误原因:不加synchronized锁就会出现多个线程抢占资源的情况,因此加锁是有必要的