Multi-Thread 4--- Lock & Conditions

1. Using reading and writing lock

Reading lock can make a data be read concurrently, but block writing thread. writeLock block all other reading and writing thread.
public class LockDemo {

	private Map<String, Object> cacheData = new HashMap<String, Object>();// this is data
	private ReadWriteLock rwl = new ReentrantReadWriteLock();
	
	//this method to get data, if not in the map, we should get access to DB, need write it back to map
	public Object getData(String key){
		rwl.readLock().lock();
		try{
			Object cache = cacheData.get(key);
			if(cache == null){
				rwl.readLock().unlock();
				rwl.writeLock().lock(); //other running read thread will lock here
				try{
					if(cache == null){//use this sentanse again to make sure other thread won't wirte again,after the
									  //first thread wirte the data back.
						cache = "aaaaa"; // go to DB to get data. 
					}
				}finally{
					rwl.writeLock().unlock();	
				}
				rwl.readLock().lock();
			}
			return cache;
		}finally{
			rwl.readLock().unlock();
		}
		
		
	}
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub

	}
}

A easier way to do this is just add synchronized key word in the definition of method.

2. Conditions

condition = lock.newCondition();
condition has method like condition.await(), and condition.signal(). it has the same function as object.wait() and object.notify(). But condition is more powerful, for it can create many conditions based  on one Lock().

For example, if we want to let thread 1, run 10 times, then thread 2 run 20 times, and then thread2 run 100 times, then goes back to thread 1. to make this loop run 30 times. we can't realize it by simply using wait() and notify. we can use Lock and conditions instead.

Business.java
public class Business {

	//lock and its conditions
	private Lock lock = new ReentrantLock();
	Condition conjob1 = lock.newCondition(); //condition that job1 should start
	Condition conjob2 = lock.newCondition(); //condition that job2 should start
	Condition conjob3 = lock.newCondition(); //condition that job3 should start
	private int flag = 1;//by default, the first job start first
	
	
	//job1, the thread runs 10 times
	public void job1(){
		lock.lock();
		try{
			while(flag != 1){ //first job should wait
				conjob1.await();
			}
			for(int i=1;i<=10;i++){
				System.out.println("job 1------------- "+i);
			}
			
			//after finish job1, it should notify job2
			flag = 2;
			conjob2.signal();
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			lock.unlock();
		}
	}
	
	//job2, the thread runs 20 times
	public void job2(){
		lock.lock();
		try{
			while(flag != 2){ //second job should wait
				conjob2.await();
			}
			for(int i=1;i<=20;i++){
				System.out.println("job 2------------- "+i);
			}
			//after finish job2, it should notify job3
			flag = 3;
			conjob3.signal();
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			lock.unlock();
		}
	}
	
	//job3, the thread runs 30 times
	public void job3(){
		lock.lock();
		try{
			while(flag != 3){ //third job should wait
				conjob3.await();
			}
			for(int i=1;i<=30;i++){
				System.out.println("job 3------------- "+i);
			}
			//after finish job1, it should notify job2
			flag = 1;
			conjob1.signal();
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			lock.unlock();
		}
	}
}

main.java
static Business business = new Business();
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		
		Runnable run1 = new Runnable(){
			@Override
			public void run() {
				// TODO Auto-generated method stub
				for(int i=1;i<30;i++){
					business.job1();
				}
				
			}
		};
		//runable2
		Runnable run2 = new Runnable(){
			@Override
			public void run() {
				// TODO Auto-generated method stub
				for(int i=1;i<30;i++){
					business.job2();
				}
			}
		};
		
		Runnable run3 = new Runnable(){
			@Override
			public void run() {
				// TODO Auto-generated method stub
				for(int i=1;i<30;i++){
					business.job3();
				}
			}
		};
		Thread t1 = new Thread(run1);
		Thread t2 = new Thread(run2);
		Thread t3 = new Thread(run3);
		t1.start();
		t2.start();
		t3.start();
		
	}
}

2.2 using Lock and condition to create a bundedBuffer( producer and consumer model)

Producers produce tokens at a solid speed and put the token into an array, and the consumer take out a token at a time and consume it. Create such a bundebuffer so that the producer thread will wait while the array is full, and the consumer thread will also wait while the array is empty.

 class BoundedBuffer {
   final Lock lock = new ReentrantLock(); //one lock
   final Condition notFull  = lock.newCondition(); //condition to see if it's full
   final Condition notEmpty = lock.newCondition(); //condition to see if it's empty

   final Object[] items = new Object[100];
   int putptr, takeptr, count;

   public void put(Object x) throws InterruptedException {
     lock.lock();
     try {
       while (count == items.length)  //if it's full
         notFull.await();  //not full conditon doesn't apply, so it wait
       items[putptr] = x;  //if it's not full, we put this token into a place
       if (++putptr == items.length) putptr = 0; //if put pointer goes to the end, we move it to the begining
       ++count;  //after put, the total amount would increase
       notEmpty.signal(); //signal a not empty condition, if there are any, becase we put one inside, we can make it not empty
     } finally {
       lock.unlock();  //unlock() in case there are some exception thrown
     }
   }

   public Object take() throws InterruptedException {
     lock.lock();
     try {
       while (count == 0)   //if it's empty, we can't take, so we have to wait
         notEmpty.await();  // so notEmpty make us waiting here
       Object x = items[takeptr]; //otherwise ,we take one item out of the array
       if (++takeptr == items.length) takeptr = 0; //if the take point goes to the end, we move it to the front
       --count;  //after take, the total amount would decrease one
       notFull.signal(); // notify the not full condition
       return x;
     } finally {
       lock.unlock();
     }
   }
 }





  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值