线程-读写锁。

读写锁。我们上次温习了synchronized与Lock.我们遗留了一个问题,就是想让读读不互斥,因为多线程同时读取数据并不会破坏数据。如果能实现读读不用互斥,那将大大提升了多线程读性能。于是我们引入了读写锁ReentrantReadWriteLock。ReentrantReadWriteLock可以专门创建一个读锁和写锁。读锁:读读不互斥,但是读写互斥。 写锁:不但读写互斥,而且写写也互斥。

创建一个读写锁

  ReadWriteLock rwl = new ReentrantReadWriteLock();

  读锁:  rwl.readLock().lock() 与 rwl.readLock().unlock(); 成对出现; 读完了公共变量,其它线程才能写这个公共变量(赋值),但是多个线程可以同时读。

  写锁: rwl.writeLock().lock() 与  rwl.writeLock().unlock(); 成对出现;写完了公共变量,其它线程才能写或读这个公共变量。

 以下示例代码展示了读锁与写锁。创建两个一个Queue自定义类,有一个get()和put()方法,在get()方法里使用读锁,在put()里使用写锁,它们都操作一个公共数据Object data。

package testFuture;

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

public class LockTest {
	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();
		}
		
	}
}


synchronized


class Queue3{
	private Object data = null;//共享数据,只能有一个线程能写该数据,但可以有多个线程同时读该数据。
	ReadWriteLock rwl = new ReentrantReadWriteLock();
	public void get(){
		rwl.readLock().lock();
		try {
			System.out.println(Thread.currentThread().getName() + " be ready to read data!");
			Thread.sleep((long)(Math.random()*1000));
			System.out.println(Thread.currentThread().getName() + "have read data :" + data);			
		} catch (InterruptedException e) {
			e.printStackTrace();
		}finally{
			rwl.readLock().unlock();
		}
	}
	
	public void put(Object data){

		rwl.writeLock().lock();
		try {
			System.out.println(Thread.currentThread().getName() + " be ready to write data!");					
			Thread.sleep((long)(Math.random()*1000));
			this.data = data;		
			System.out.println(Thread.currentThread().getName() + " have write data: " + data);					
		} catch (InterruptedException e) {
			e.printStackTrace();
		}finally{
			rwl.writeLock().unlock();
		}
		
	
	}
}

打印日志如下:

Thread-2 be ready to read data!
Thread-0 be ready to read data!
Thread-4 be ready to read data!
Thread-0have read data :null
Thread-2have read data :null
Thread-4have read data :null
Thread-5 be ready to write data!
Thread-5 have write data: 8687
Thread-5 be ready to write data!
Thread-5 have write data: 8653
Thread-1 be ready to write data!
Thread-1 have write data: 7614
Thread-1 be ready to write data!
Thread-1 have write data: 4680
Thread-3 be ready to write data!
Thread-3 have write data: 473
Thread-0 be ready to read data!
Thread-2 be ready to read data!
Thread-4 be ready to read data!
Thread-0have read data :473
Thread-4have read data :473
Thread-2have read data :473
Thread-5 be ready to write data!
Thread-5 have write data: 7706
Thread-1 be ready to write data!
Thread-1 have write data: 7828
Thread-1 be ready to write data!
Thread-1 have write data: 6492
Thread-3 be ready to write data!
Thread-3 have write data: 6439
Thread-3 be ready to write data!
Thread-3 have write data: 4558
Thread-0 be ready to read data!
Thread-4 be ready to read data!
Thread-2 be ready to read data!
Thread-0have read data :4558
Thread-4have read data :4558
Thread-2have read data :4558

 

我们会发现总共有6个线程:0,2,4线程是读,1,3,5线程是写数据,当5在写数据的时候,put方法输出以下2条日志:

Thread-5 be ready to write data!
Thread-5 have write data: 8687

这2条日志之间,并没有其它线程打扰。5写完了,接着才是线程1写数据,输出日志:

Thread-1 be ready to write data!
Thread-1 have write data: 7614

同样,这2条日志之间,没有其它线程打扰。

假设线程5在执行put写数据的时候,输出日志如下,则是被线程1打扰了:

Thread-5 be ready to write data!

Thread-1 be ready to write data!
Thread-5 have write data: 8687

Thread-1 have write data: 7614

线程5的本意是让data变为8676,结果当线程5的put返回的时候,实际上data已被线程1修改成了7614,线程5还摸不着头脑,自己怎么就做错了,很简单的事情都能出错。

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

冉航--小虾米

希望得到您的鼓励和交流

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值