实现线程同步的三种方法:同步代码块,同步方法,Lock锁
首先以银行取款为例:张三与其妻子同时对一个银行账户进行取款操作,此过程涉及三个类即银行账户类Account,取款线程AccountRunnable 及测试类TestAccount 线程同步的三种方法只是AccountRunnable的不同,因此可将Account,TestAccount提出来
银行账户类
package com.yue.synch0;
public class Account {
private int balance=600;//默认存款600元
public void withDraw(int money) {
//取款
this.balance = this.balance - money;
}
public int getBalance() {
return balance;//查看余额
}
}
测试类
package com.yue.synch0;
public class TestAccount {
public static void main(String[] args) {
Runnable runnable = new AccountRunnable();
Thread thread1 = new Thread(runnable, "张三");
Thread thread2 = new Thread(runnable, "张三妻子");
thread1.start();
thread2.start();
}
}
第一种:同步代码块
synchronized(同步监视器){ }
总结1:认识同步监视器(锁子) //类中的account
1)必须是引用数据类型,不能是基本数据类型
2)在同步代码块中可以改变同步监视器对象的值,不能改变其引用
3)一般使用共享资源做同步监视器即可
4)建议使用final修饰同步监视器
总结2:同步代码块的执行过程
1)第一个线程来到同步代码块,发现同步监视器open状态,需要close,然后执行其中的代码
2)第一个线程执行过程中,发生了线程切换(阻塞 就绪),第一个线程失去了cpu,但是没有开锁open
3)第二个线程获取了cpu,来到了同步代码块,发现同步监视器close状态,无法执行其中的代码,第二个线程也进入阻塞状态
4)第一个线程再次获取CPU,接着执行后续的代码;同步代码块执行完毕,释放锁open
5)第二个线程也再次获取cpu,来到了同步代码块,发现同步监视器open状态,重复第一个线程的处理过程(加锁)
强调:同步代码块中能发生线程切换吗?能!!! 但是后续的被执行的线程也无法执行同步代码块(锁仍旧close)
总结3:线程同步 优点和缺点
优点:安全
缺点:效率低下 可能出现死锁
总结4:其他
1)多个代码块使用了同一个同步监视器(锁),锁住一个代码块的同时,也锁住所有使用该锁的所有代码块,