Java多线程学习笔记3——ReentranLock和ReentrantReadWriteLock

本文深入探讨了Java中的多种同步机制,包括synchronized关键字、synchronized代码块、Lock接口及其实现ReentrantLock和ReentrantReadWriteLock,并对比了这些同步机制的特点与应用场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在java中实现的同步的方式有很多如同步工具类CountDownLatch,CyclicBarrier。synchronized方法,synchronized代码块。

synchronized方法,有一定的局限性作用的区域受限,有时代码可能只需要方法中某一行或者几行代码要同步,不许要整个方法同步影响程序性能或则造成程序错误。这个时候可以使用synchronized代码块,而且代码块有更灵活的锁机制可以使用自定义的对象作为锁,也可以使用当前对象作为锁。

synchronized代码块代码块更灵活,可以自己控制同步的代码范围。也可以自己定义同步锁。synchronized方法如果是实例方法,同步锁就是this,实例对象。静态方法同步锁就是类本身。

 Jdk 5推出一个同步工具 Lock 接口他的实现对象有ReentranLock,ReentrantReadWriteLock等,只要调用lock方法就可以加锁,unlock方法就可以释放锁。

下面对比下 lock 和  synchronized:

1)Lock是一个接口,而synchronized是Java中的关键字,synchronized是内置的语言实现,更加符合面向对象的思想;

2)synchronized在发生异常时,会自动释放线程占有的锁,因此不会导致死锁现发象生;而Lock在发生异常时,如果没有主动通过unLock()去释放锁,则很可能造成死锁现象,因此使用Lock时需要在finally块中释放锁;

3)Lock可以让等待锁的线程响应中断,通过interrupt方法。而synchronized却不行,使用synchronized时,等待的线程会一直等待下去,不能够响应中断;如果遇到IO操作比较耗时,会影响运行效率。

4)通过Lock可以知道有没有成功获取锁,而synchronized却无法办到。使用 lock.tryLock()获取true或则false判断判断是否拿到锁。

5)Lock可以提高多个线程进行读操作的效率。ReadWriteLock,一个用来获取读锁,一个用来获取写锁。也就是说将文件的读写操作分开,分成2个锁来分配给线程,从而使得多个线程可以同时进行读操作。提高处理效率。

 

 ReentrantReadWriteLock更是可以对读写两种不同的情况分别加锁。具体情景如下:写的时候不能读取数据,而且写之间是互斥的,读的时候不互斥。代码如下:

public class ReadWriterLock {
	public static void main(String[] args) {
		final Queue3 q3 = new Queue3();
		for (int i = 0; i < 3; i++) {
			new Thread() {
				public void run() {
					while (true) {
						q3.get();
					}
				};
			}.start();
			new Thread() {
				public void run() {
					while (true) {
						q3.put(new Random().nextInt(10000));
					}
				};
			}.start();
		}
	}
}
class Queue3 {
	private Object data = 0;
	private ReadWriteLock rwL = new ReentrantReadWriteLock();
	public  void get() {
		rwL.readLock().lock();
		try {
			System.out.println(Thread.currentThread().getName() + " ready   read   data!");
			Thread.sleep((long) (Math.random() * 1000));
			System.out.println(Thread.currentThread().getName() + "have   read   data!"+this.data.toString());
		} catch (InterruptedException e) {
			e.printStackTrace();
		}finally{
			rwL.readLock().unlock();
		}	
	}
	public void put(Object data) {
		rwL.writeLock().lock();
		try {
			System.out.println(Thread.currentThread().getName() + " ready  write data!");
			this.data = data;
			Thread.sleep((long) (Math.random() * 1000));
			System.out.println(Thread.currentThread().getName() + "have  write  data!"+this.data.toString());
		} catch (InterruptedException e) {
			e.printStackTrace();
		}finally{
			rwL.writeLock().unlock();
		}
	}
}

以上实现了写和读之间的互斥。使用此特点可以设计一个缓存系统:代码如下

ConcurrentHashMap<String, String>  hashMap=new  ConcurrentHashMap<>(); 
	
	public String get(String key){
		ReadWriteLock  readWriteLock=new ReentrantReadWriteLock();
		readWriteLock.readLock().lock();
		if(hashMap.containsKey(key)){
			return hashMap.get(key);
		}else{
			readWriteLock.readLock().unlock();
			readWriteLock.writeLock().lock();
			String  db=null;
			if(!hashMap.containsKey(key)){
			    db=new Random()+"123aaa";
				hashMap.put(key,db);
			}
			readWriteLock.writeLock().unlock();
			return db;
		}
	}

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值