多线程总结五:Java1.5并发Lock

一.概述

  1. java1.5为我们提供了同步控制的新途径, java.util.concurrent.locks.*提供了两个核心接口:Lock,Condition。
  2. Lock接口提供了比synchronized关键字同步流程更加清晰的方法。
  3. Condition接口替代了object对象的三个监视方法。

二.代码

  1. 传统synchronized + wait + notify控制同步。
    package com.zzy.syn;
    
    /**
     * 传统同步方式
     * synchronized + wait + notify
     * @author eason
     *
     */
    public class TestSynchronized {
    
    	public static void main(String[] args) {
    		final Service service = new Service();
    		
    		new Thread(new Runnable() {
    			@Override
    			public void run() {
    				service.subThread();          //新线程调用subThread方法
    				
    			}
    		}).start();
    		
    		service.mainThread();                //主线程调用mainThread方法
    	}
    	
    	static class Service {
    		
    		private boolean shouldSubRun = true;   //此时是否该执行subThread方法
    		
    		public synchronized void mainThread() {
    			while(shouldSubRun) {       
    				try {
    					wait();         //该执行subThread方法,调用mainThread方法的主线程等待
    				} catch (InterruptedException e) {
    					e.printStackTrace();
    				}
    			}
    			
    			System.out.println("mainThread method execute");  //逻辑区域
    			shouldSubRun = true;        //mainThread方法执行完后,该执行subThread方法
    			notify();                   //唤醒等待在subThread方法上的的新线程
    		}
    
    		public synchronized void subThread() {
    			while(!shouldSubRun) {      
    				try { 
    					wait();           //该执行mainThread方法,调用subThread方法的新线程等待
    				} catch (InterruptedException e) {
    					e.printStackTrace();
    				}
    			}
    				
    			System.out.println("subThread method execute");  //逻辑区域
    			shouldSubRun = false;     //subThread方法执行完后,该执行mainThread方法
    			notify();                 //唤醒等待在mainThread方法上的的主线程
    		}
    	}
    		
    }
     
  2. Lock+Condition控制同步。
    package com.zzy.syn;
    
    import java.util.concurrent.locks.Condition;
    import java.util.concurrent.locks.Lock;
    import java.util.concurrent.locks.ReentrantLock;
    
    /**
     * java1.5提供的同步方式
     * lock + condition
     * @author eason
     *
     */
    public class TestLock {
    
    	public static void main(String[] args) {
    		final Service service = new Service();
    		
    		//线程sub1调用service的sub1方法
    		new Thread(new Runnable() {
    			@Override
    			public void run() {
    				service.sub1();
    				
    			}
    		}, "sub1").start();
    		//线程sub2调用service的sub2方法
    		new Thread(new Runnable() {
    			@Override
    			public void run() {
    				service.sub2();
    				
    			}
    		}, "sub2").start();
    		//线程sub3调用service的sub31方法
    		new Thread(new Runnable() {
    			@Override
    			public void run() {
    				service.sub3();
    				
    			}
    		}, "sub3").start();
    		
    	}
    	
    	static class Service {
    		
    		private int shouldSubNum = 1;                  //此时该sub几方法执行
    		private Lock lock = new ReentrantLock();
    		Condition sub1 = lock.newCondition();
    		Condition sub2 = lock.newCondition();
    		Condition sub3 = lock.newCondition();
    		
    		public void sub1() {
    			lock.lock();
    			try{
    				while(shouldSubNum != 1) {       
    					try {
    						sub1.await(); //该sub2或sub3方法执行时,调用sub1方法的sub1线程等待
    					} catch (InterruptedException e) {
    						e.printStackTrace();
    					}
    				}
    				
    				System.out.println("sub1 method execute");
    				shouldSubNum = 3;                     //sub1方法线程完后,轮到sub3执行
    				sub3.signal();                        //唤醒调用sub3方法的sub3线程
    			} finally {
    				lock.unlock();
    			}
    		}
    		
    		public void sub2() {
    			lock.lock();
    			try{
    				while(shouldSubNum != 2) {       
    					try {
    						sub2.await(); //该sub1或sub3方法执行时,调用sub2方法的sub2线程等待
    					} catch (InterruptedException e) {
    						e.printStackTrace();
    					}
    				}
    				
    				System.out.println("sub2 method execute");
    				shouldSubNum = 1;                    //sub2方法线程完后,轮到sub1执行
    				sub1.signal();                       //唤醒调用sub1方法的sub1线程
    			} finally {
    				lock.unlock();
    			}
    		}
    		
    		public void sub3() {
    			lock.lock();
    			try{
    				while(shouldSubNum != 3) {       
    					try {
    						sub3.await(); //该sub1或sub2方法执行时,调用sub3方法的sub3线程等待
    					} catch (InterruptedException e) {
    						e.printStackTrace();
    					}
    				}
    				
    				System.out.println("sub3 method execute");
    				shouldSubNum = 2;                    //sub3方法线程完后,轮到sub2执行
    				sub2.signal();                       //唤醒调用sub2方法的sub2线程
    			} finally {
    				lock.unlock();
    			}
    		}
    
    	}
    		
    }
     

三.二者对比

  1. Lock接口提供了比synchronized更加广泛和灵活的操作。
    1. Lock接口的实现允许锁在不同的作用范围内获取和释放,并允许以任何顺序获取和释放多个锁。上例一个反应出来了。
    2. 其他的用到在写。
  2. synchronized是在JVM 层面上实现的,Lock是在代码层面实现的。
  3. synchronized在锁定时如果方法块抛出异常,JVM 会自动将锁释放掉,不会因为出了异常没有释放锁造成线程死锁。但是 Lock 的话就享受不到 JVM 带来自动的功能,出现异常时必须在 finally 将锁释放掉,否则将会引起死锁。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值