Java读写锁

ReentrantLock

ReentrantLock它实现了标准的互斥锁,即当一个线程获取了锁,其他的线程都要等待,当前线程释放锁才能获得所有权。一次最多只有一个线程持有锁。通常作为保护数据一致性很强的的加锁约束,这样也就限制了程序的并发效率。

虽然避免了 写---写,读---写 的线程安全问题,但是也同样避开了读读的的重叠。在很多的时候数据是被频繁读取的。

ReentrantReadWriteLock  

它的出现就是为了解决多个线程读读互斥的问题。

我们先来看JavaDoc文档中两个获取锁模式 ------------:

  1. 不公平的(竞争)模式
 * <dl>
 * <dt><b><i>Non-fair mode (default)</i></b>
 * <dd>When constructed as non-fair (the default), the order of entry
 * to the read and write lock is unspecified, subject to reentrancy
 * constraints.  A nonfair lock that is continuously contended may
 * indefinitely postpone one or more reader or writer threads, but
 * will normally have higher throughput than a fair lock.

当创建一个非公平的锁,受制于重入的约束 ,它获得锁的读写顺序是没有被指定的。一个非公平的锁将会无限期的延误另一个读或者写的线程,但却拥有更高的吞吐量。

   2.公平的模式

 * <dt><b><i>Fair mode</i></b>
 * <dd>When constructed as fair, threads contend for entry using an
 * approximately arrival-order policy. When the currently held lock
 * is released, either the longest-waiting single writer thread will
 * be assigned the write lock, or if there is a group of reader threads
 * waiting longer than all waiting writer threads, that group will be
 * assigned the read lock.
  •  线程不用一个近似到达的顺序来争夺进入,当线程释放锁时,会优先的选择一个单个的等待时间最长的读线程的来获得锁
  • 如果有一组读线程的等待时间是大于所有的写线程是,这些读操作的线程会优先的获取
  • 如果写锁被持有,或者有个写的线程在等待,去获取它的读锁就会发生阻塞。线程将不会获得读锁,直到在当前等待时间最长的写入线程获得并释放写入锁之后。
  • 一个线程想要获得公平的写锁将会被阻塞,除非它的读锁或者写锁都是没有被占用的。即只要一个一线程获取公平写锁,只要它被读锁占用或者被写锁占用都会发生阻塞。

读写锁的作用: 刷新缓存,改进集合

package ReadWirteLock;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * 
 * @author Administrator
 *
 */

public class ReenterantLock {
	
	private final ReentrantReadWriteLock readWriteLock =new ReentrantReadWriteLock();
	private final Map<String,Object> cache = new HashMap<>();
	private final Lock readlock = readWriteLock.readLock();
	private final Lock writeLock = readWriteLock.writeLock();
	
	//读的时候是可以被多个线程读取访问的
	public Object get(String key) {
		readlock.lock();
		Object val;
		try {
			return cache.get(key);
		} finally {
			readlock.unlock();
		}
	}
	
	public void set(String key,Object value) {
		// Must release read lock before acquiring write lock  or willed be blocked;
		writeLock.lock();
		try {
			cache.put(key, value);
		} finally {
			writeLock.unlock();
		}
	}
}

测试锁降级:

package ReadWirteLock;

import java.sql.Time;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * 
 * @author Administrator
 *
 */

public class ReenterantLock {
	
	private final ReentrantReadWriteLock readWriteLock =new ReentrantReadWriteLock();
	private final Map<String,Object> cache = new HashMap<>();
	private final Lock readlock = readWriteLock.readLock();
	private final Lock writeLock = readWriteLock.writeLock();
	
	//读的时候是可以被多个线程读取访问的
	public Object get(String key) {
		readlock.lock();
		Object val;
		try {
			System.out.println("开始读取key:"+key);
			return cache.get(key);
		} finally {
			System.out.println("结束key:"+key);
			readlock.unlock();
		}
	}
	
	public void set(String key,Object value) {
		// Must release read lock before acquiring write lock  or willed be blocked;
		writeLock.lock();
		try {
			cache.put(key, value);
		} finally {
			writeLock.unlock();
		}
	}
	
	public static void main(String[] args) {
		
		ReenterantLock reenterantLock =new ReenterantLock();
		for(int i=0;i<10;i++) {
			System.out.println("放置数据");
			reenterantLock.set(String.valueOf(i), i);
		}
		
		Thread t1 =new Thread(() -> {
			try {
				Thread.currentThread().sleep(1000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			reenterantLock.set("4", 4);
			for(int i=0;i<3;i++) {
				System.out.println("t1 开始锁降级  get key:"+i);
				reenterantLock.get(String.valueOf(i));
			}
		});
		
		Thread t2 =new Thread(() -> {
			try {
				Thread.currentThread().sleep(1000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			for(int i=0;i<10;i++) {
				reenterantLock.get(String.valueOf(i));
			}
		});
		
		t1.start();
		t2.start();
		
	}
}

猜你喜欢

转载自blog.csdn.net/qq_24532581/article/details/86640821