jdk1.5——readLock/writeLock

1 关于读写锁的一些特点

  a) 读写锁是JVM自己控制的,我们只要上相应方法上加锁即可

  b) 多个读锁共享数据/操作

  c) 读锁和写锁行为互斥

  d) 写锁和写锁行为互斥

2 读写锁应用案例1,

package thread;

import java.util.Random;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * 多线程下
 * 写的时候 独占
 * 读的时候 共享    分别在对应的方法上 增加 读/写锁,剩下关于独占和共享功能交给jdk5来完成。
 * @author zm
 *
 */
public class ReadWriteLockExamp {

	/**
	 * 如下数据说明:  线程在读的时候 没有写行为     同样 线程写时没有读行为
Thread-0  be ready to read data!
Thread-0  read the data is 0
Thread-1  be ready to write data!
Thread-1  write the data is 1667
Thread-2  be ready to read data!
Thread-2  read the data is 1667
Thread-3  be ready to write data!
Thread-3  write the data is 6691
Thread-4  be ready to read data!
Thread-4  read the data is 6691
Thread-5  be ready to write data!
Thread-5  write the data is 6950
Thread-6  be ready to read data!
Thread-8  be ready to read data!
Thread-6  read the data is 6950
Thread-8  read the data is 6950
Thread-7  be ready to write data!
Thread-7  write the data is 1142
Thread-9  be ready to write data!
Thread-9  write the data is 331
	 */
	public static void main(String[] args) {
		
		final Quene quene = new Quene();
		
		for(int i=0; i<5; i++){
			
			new Thread(new Runnable() {
				
				@Override
				public void run() {
					quene.readData();
				}
			}).start();
			
			new Thread(new Runnable() {
				
				@Override
				public void run() {
					quene.writeData();
				}
			}).start();
			
			
		}
		
		
		
	}

}

class Quene {
	
	private int data;
	ReadWriteLock lock = new  ReentrantReadWriteLock();
	
	public void readData(){ // 增加读锁 大家都在读数据 为了防止读的过程中别人同时写东西,因此需要加入读锁
		try {
			lock.readLock().lock();
			System.out.println(Thread.currentThread().getName() + "  be ready to read data!");
			Thread.sleep(10);
			System.out.println(Thread.currentThread().getName() + "  read the data is " + data);
		} catch (Exception e) {
			e.printStackTrace();
		}finally{
			lock.readLock().unlock();// 及时关闭
		}
		
	}
	
	
	public void writeData(){  // 增加写锁
		
		try {
			lock.writeLock().lock();
			System.out.println(Thread.currentThread().getName() + "  be ready to write data!");
			Thread.sleep(100);
			data = new Random().nextInt(10000);
			System.out.println(Thread.currentThread().getName() + "  write the data is " + data);
		} catch (Exception e) {
			e.printStackTrace();
		}finally{
			lock.writeLock().unlock(); // 及时关闭
		}
		
	}
	
	
	
}

3 利用读写锁模拟一个缓存系统,

   写法参考 API下类 ReentrantReadWriteLock 下 class CachedData {...}  细节自行查找

package thread;

import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

public class MyCache {

	/**
	 * 
	 */
	public static void main(String[] args) {

		
	}

}

class CacheData {
	
	String value = "";
	ReadWriteLock lock = new ReentrantReadWriteLock();
	
	public String processCacheData(){
		lock.readLock().lock();
		try{
			if("".equals(value)){// 找不到数据
				lock.readLock().unlock();// 放掉读锁,带上写锁(因为读写锁互斥)
				lock.writeLock().lock();// 当最早的线程加写锁后,其余稍后的并发过来的读线程被互斥等待,直到最先的线程执行到 释放写锁后,才能继续执行后续代码
				try{
					if("".equals(value)){// 这里必须在又一次非空判断,防止 第一次时并发过来时 重复执行赋值操作
						value = "hello hadoop"; // 真实代码为业务逻辑 eg: get user from db
					}
				}finally{
					lock.writeLock().unlock(); // 写完数据后放弃写锁
				}
				lock.readLock().lock();// 增加读锁,防止稍后线程获取到写锁,执行重写写操作
			}	
		}finally{
			lock.readLock().unlock(); // 为了防止业务层出现异常,因此所有的释放锁操作都要放在finally执行
		}
		
		
		return value;
		
	}

	
}

4 读写锁适应的环境:

以下从jdk ReadWriteLock api下部分摘抄:

与互斥锁相比,使用读-写锁所允许的并发性增强将带来更大的性能提高
在实践中,只有在多处理器上并且只在访问模式适用于共享数据时,才能完全实现并发性增强。
如果数据更新变得频繁,数据在大部分时间都被独占锁,这时,就算存在并发性增强,也是微不足道的
如果读取操作所用时间太短,则读-写锁实现(它本身就比互斥锁复杂)的开销将成为主要的执行成本
只有通过分析和测量,才能确定应用程序是否适合使用读-写锁。

总结就是: 仅仅适合于 大量读, 少量写的场合

5 脑图:



 

猜你喜欢

转载自chengjianxiaoxue.iteye.com/blog/2145210