java学习初探十八之线程的线程同步_锁机制_synchronized
2017-12-21 20:00
393 查看
一、线程同步
异步线程模型:t1线程执行t1的,t2线程执行t2的,两个线程之间谁也不等谁。
同步线程模型:t1线程和t2线程执行,当t1线程必须等t2线程执行结束之后,t1线程才能执行。
1.以下例子为没使用线程同步的情况:
输出:
显而易见,这是不正确的。
2.以下程序使用线程机制控制(synchronized):
输出:
3.执行原理:
t1线程执行到此处,遇到,synchronized关键字,就会去找this的对象锁。如果找到this对象锁,则进入同步语句块中执行程序。当同步语句块中的语句块执行结束后,t1线程归还this的对象锁。
在t1线程执行同步语句块的过程中,如果t2线程也过来执行,也遇到synchronized关键字,所以也去找this的对象锁,但是该对象锁被t1线程所有,只能在这等待this对象的归还。
sychronized关键字添加到成员方法上,线程拿走的也是this的对象锁。
为了精确控制,2的添加方法更适合些。
4.面试题
输出结果:
5.类锁 ,修饰静态方法
6.死锁
异步线程模型: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........
5.类锁 ,修饰静态方法
package xiancheng2; /* * 类锁,类只有一个,所以锁是类级别的,只有一个 */ public class ThreadTest3 { public static void main(String[] args) throws InterruptedException { Thread t1=new Thread(new Proccessor()); t1.setName("t1"); Thread t2=new Thread(new Proccessor()); t2.setName("t2"); t1.start(); Thread.sleep(1000); t2.start(); } } class Proccessor implements Runnable{ public void run() { if("t1".equals(Thread.currentThread().getName())) { Myclass.m1(); } if("t2".equals(Thread.currentThread().getName())) { Myclass.m2(); } } } class Myclass{ //synchronized添加到静态方法上,线程执行此方法的时候会找类锁 public synchronized static void m1() { try { Thread.sleep(10000); } catch (Exception e) { } System.out.println("m1......."); } //不会等m1结束,因为该方法没有被sychronized修饰。 /*public static void m2() { System.out.println("m2......."); } */ //会等m1结束,因为该方法没有被sychronized修饰。线程执行该代码需要“类锁”,而类锁只有一个 public synchronized static void m2() { System.out.println("m2......."); } }
6.死锁
package xiancheng2; /* * 死锁 */ public class ThreadTest1 { public static void main(String[] args) { Object o1=new Object(); Object o2=new Object(); Thread t1=new Thread(new T1(o1,o2)); Thread t2=new Thread(new T2(o1,o2)); t1.start(); t2.start(); } } class T1 implements Runnable{ Object o1; Object o2; T1(Object o1,Object o2){ this.o1=o1; this.o2=o2; } public void run() { //先锁o1,再锁o2 synchronized (o1) { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("t11...."); synchronized (o2) { System.out.println("t1...."); } } } } class T2 implements Runnable{ Object o1; Object o2; T2(Object o1,Object o2){ this.o1=o1; this.o2=o2; } public void run() { //先锁o2,再锁o1 synchronized (o2) { try { Thread.sleep(1000); } catch (Exception e) { } System.out.println("t22...."); synchronized (o1) { System.out.println("t2...."); } } } }
相关文章推荐
- java学习初探十八之线程的调度与控制_sleep
- java学习初探十八之线程的守护线程
- java学习初探十八之线程的Timer定时器
- java学习初探十八之线程和进程的区别
- java学习初探十八之线程的调度与控制_让位yield_合并jion
- java学习初探十八之线程的创建和启动
- java学习初探十八之线程的生命周期
- Java线程(二):线程同步synchronized和volatile
- Java线程(二):线程同步synchronized和volatile .
- Java基础学习5_多线程(线程间通信--等待唤醒机制)
- java多线程学习一线程安全之内存、synchronized、volatile
- Java线程(二):线程同步synchronized和volatile
- java线程学习5——线程同步之同步方法
- Java线程(二):线程同步synchronized和volatile
- java线程间通信_线程同步_等待唤醒机制
- Java--线程同步(使用了synchronized)和线程通讯(使用了wait,notify)
- Java线程(二):线程同步synchronized和volatile
- java线程学习4——线程同步之同步代码块
- Java线程同步机制synchronized关键字的理解
- 【Java线程】锁机制:synchronized、Lock、Condition