java学习初探十八之线程的线程同步_锁机制_synchronized
来源:互联网 发布:mac压缩包加密 编辑:程序博客网 时间:2024/05/17 05:53
一、线程同步
异步线程模型:t1线程执行t1的,t2线程执行t2的,两个线程之间谁也不等谁。
同步线程模型:t1线程和t2线程执行,当t1线程必须等t2线程执行结束之后,t1线程才能执行。
什么时候要同步?为什么要引入线程同步?1.为了数据的安全。尽管应用程序的使用率降低,但是为了保证数据是安全的,必须加入线程同步机制。线程同步机制使程序变成了(等同)单线程2.什么情况下要使用线程同步?第一、必须是多线程环境;第二、多线程环境共享同一个数据;第三、共享数据涉及修改操作。
1.以下例子为没使用线程同步的情况:
package xiancheng2;/* * 以下程序演示取款离职。以下程序不使用线程同步机制, * 多线程同时对同一个账号进行取款操作,会出现什么问题? */public class ThreadTest1 { public static void main(String[] args) { //创建公共账号 Account act=new Account("actno-001",5000); //创建线程对同一个账号取款 Proccessor p=new Proccessor(act); Thread t1=new Thread(p); Thread t2=new Thread(p); t1.start(); t2.start(); }}//取款线程class Proccessor implements Runnable{ //账号 Account act; public Proccessor(Account act) { this.act=act; } public void run() { act.withdraw(1000.0); System.out.println("取款成功,余额"+act.getBalance()); }}//账号class Account{ private String actno; private double balance; public Account() {} public Account(String actno,double balance) { this.balance=balance; this.actno=actno; } 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=this.balance-money; //延迟 try {Thread.sleep(5000);} catch (Exception e) { e.printStackTrace(); } //更新 this.setBalance(after); }}
输出:
取款成功,余额4000.0取款成功,余额4000.0
显而易见,这是不正确的。
2.以下程序使用线程机制控制(synchronized):
package xiancheng2;/* * 以下程序演示取款离职。以下程序不使用线程同步机制, * 多线程同时对同一个账号进行取款操作,会出现什么问题? */public class ThreadTest1 { public static void main(String[] args) { //创建公共账号 Account act=new Account("actno-001",5000); //创建线程对同一个账号取款 Proccessor p=new Proccessor(act); Thread t1=new Thread(p); Thread t2=new Thread(p); t1.start(); t2.start(); }}//取款线程class Proccessor implements Runnable{ //账号 Account act; public Proccessor(Account act) { this.act=act; } public void run() { act.withdraw(1000.0); System.out.println("取款成功,余额"+act.getBalance()); }}//账号class Account{ private String actno; private double balance; public Account() {} public Account(String actno,double balance) { this.balance=balance; this.actno=actno; } 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) {//对当前账号进行取款操作 //把需要同步的代码,放到同步语句块中。 synchronized (this) {//填共享对象 double after=this.balance-money; //延迟 try {Thread.sleep(5000);} catch (Exception e) { e.printStackTrace(); } //更新 this.setBalance(after); } }}
输出:
取款成功,余额4000.0取款成功,余额3000.0
3.执行原理:
t1线程执行到此处,遇到,synchronized关键字,就会去找this的对象锁。如果找到this对象锁,则进入同步语句块中执行程序。当同步语句块中的语句块执行结束后,t1线程归还this的对象锁。
在t1线程执行同步语句块的过程中,如果t2线程也过来执行,也遇到synchronized关键字,所以也去找this的对象锁,但是该对象锁被t1线程所有,只能在这等待this对象的归还。
sychronized关键字添加到成员方法上,线程拿走的也是this的对象锁。
package xiancheng2;/* * 以下程序演示取款离职。以下程序不使用线程同步机制, * 多线程同时对同一个账号进行取款操作,会出现什么问题? */public class ThreadTest1 { public static void main(String[] args) { //创建公共账号 Account act=new Account("actno-001",5000); //创建线程对同一个账号取款 Proccessor p=new Proccessor(act); Thread t1=new Thread(p); Thread t2=new Thread(p); t1.start(); t2.start(); }}//取款线程class Proccessor implements Runnable{ //账号 Account act; public Proccessor(Account act) { this.act=act; } public void run() { act.withdraw(1000.0); System.out.println("取款成功,余额"+act.getBalance()); }}//账号class Account{ private String actno; private double balance; public Account() {} public Account(String actno,double balance) { this.balance=balance; this.actno=actno; } 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 synchronized void withdraw(double money) {//对当前账号进行取款操作 double after=this.balance-money; //延迟 try {Thread.sleep(5000);} catch (Exception e) { e.printStackTrace(); } //更新 this.setBalance(after); }}
为了精确控制,2的添加方法更适合些。
4.面试题
package xiancheng2;/* * 面试题 * t1线程没有结束的时候,t2需不需要等t1结束? * 答案:不需要。 * 因为m2方法上没有synchronized,所以不需要找对象锁。 * 如果m2方法上加了synchronized,则需要找对象锁,等待m1方法结束,释放对象锁。 * 注意:t1、t2一定要共享同一个对象,才能谈同步机制。 */public class ThreadTest2 { public static void main(String[] args) throws InterruptedException { MyClass mc=new MyClass(); myThread thread=new myThread(mc); Thread t1=new Thread(thread); t1.setName("t1"); Thread t2=new Thread(thread); t2.setName("t2"); //启动线程 t1.start(); //延迟保证t1线程先启动,并执行run Thread.sleep(1000); t2.start(); }}class myThread implements Runnable{ MyClass mc; myThread(MyClass mc){ this.mc=mc; } public void run() { if(Thread.currentThread().getName().equals("t1")) { mc.m1(); } if(Thread.currentThread().getName().equals("t2")) { mc.m2(); } }}class MyClass{ public synchronized void m1() { //休眠10s try{Thread.sleep(10000);}catch (InterruptedException e) {} System.out.println("m1........"); } public void m2() { System.out.println("m2........"); }}
输出结果:
m2........m1........
阅读全文
0 0
- java学习初探十八之线程的线程同步_锁机制_synchronized
- java学习初探十八之线程的调度与控制_优先级
- java学习初探十八之线程的调度与控制_让位yield_合并jion
- java学习初探十八之线程和进程的区别
- java学习初探十八之线程的创建和启动
- java学习初探十八之线程的生命周期
- Java线程的学习_线程同步
- java学习初探十八之线程的调度与控制_sleep
- java线程技术5_synchronized
- Java线程学习之线程初探
- [线程]——线程同步与锁定1_synchronized
- [线程]——线程同步与锁定2_synchronized
- 【Java并发学习】之线程的同步
- Java并发学习之十八——线程同步工具之CyclicBarrier
- [Java]_[线程同步]
- Java线程学习笔记之线程同步
- Java基础第十二天学习日记_线程、线程的同步、线程间通讯
- 3、线程安全_synchronized
- 跨域的问题
- Listview下啦刷新
- angularjs作用域及其生命周期
- 算法实验1《分治算法实验》
- JAVA-Swing图形化界面之事件监听1
- java学习初探十八之线程的线程同步_锁机制_synchronized
- python函数的知识点:
- Attention
- Python 生成一组随机数列表
- 开心斗地主【多组实例测试】
- 原生无框架JDBC实现数据库连接和Servlet页面的基本操作
- Linux 中 创建用户、设置密码、切换用户 的方法
- 关于Android中的AlarmManager使用后不唤醒的问题
- Android 语言国际化