synchronized、Lock、ReadWriteLock(读写锁例子 CacheDemo)

一、synchronized:它是java中的一个关键字,它能够把任意一个非NULL的对象看成锁。java

1)做用于方法时,锁住的是对象的实例(this);缓存

2)看成用于静态方法时,锁住的是Class实例,又由于Class的相关数据存储在永久带PermGen(jdk1.8则是metaspace),永久带是全局共享的,所以静态方法锁至关于类的一个全局锁,会锁全部调用该方法的线程;并发

3)synchronized做用于一个对象实例时,锁住的是全部以该对象为锁的代码块。性能

 

二、Lock:Lock有一个实现类:ReentrantLock,它实现了Lock里面的方法,可是使用Lock的时候必须注意它不会像synchronized执行完成以后或者抛出异常以后自动释放锁,而是须要你主动释放锁,因此咱们必须在使用Lock的时候加上try{}catch{}finally{}块,而且在finally中释放占用的锁资源。this

Lock和synchronized最大的区别就是当使用synchronized,一个线程抢占到锁资源,其余线程必须等待;而使用Lock,一个线程抢占到锁资源,其余的线程能够不等待或者设置等待时间,实在抢不到能够去作其余的业务逻辑。spa

三、ReadWriteLock(读读共享,其余全互斥):它能够实现读写锁,当读取的时候线程会得到read锁,其余线程也能够得到read锁同时并发的去读取,可是写程序运行获取到write锁的时候,其余线程是不能进行操做的,由于write是排它锁,而上面介绍的两种无论你是read仍是write没有抢到锁的线程都会被阻塞或者中断,它也是个接口,里面定义了两种方法readLock()和readLock(),他的一个实现类是ReentrantReadWriteLock。线程

关于读写锁的一个缓存例子CacheDemo:code

package resource.java.ordinary.mul.thread;

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

/**
 * 一个缓存demo,读写锁例子,实现读和写互斥、写和写互斥,但有能够多个并发的读,可提升系统性能
 * 
 * @author xiao
 */
public class CacheDemo {
	// 数据
	private Map<String, Object> cache = new HashMap<>();
	// 读写锁
	private ReadWriteLock rwl = new ReentrantReadWriteLock();

	public Object getData(String key) {
		// 上读锁,多个读时能够并发,不会形成对数据的破坏
		rwl.readLock().lock();
		Object value = null;
		try {
			value = cache.get(key);
			// 若是数据为空
			if (value == null) {
				// 释放读锁上写锁,上写锁后,数据不能被读
				rwl.readLock().unlock();
				rwl.writeLock().lock();
				try {
					// 此处判断是为防止多个线程同时进入到这里时,多个线程对数据进行重复写
					if (value == null) {
						// 若是没有数据,则去查DB获取数据
						value = "XXX";
					}
				} finally {
					// 读取数据后释放写锁
					rwl.writeLock().unlock();
				}
				// 获取完数据后,恢复读锁,从新读取数据
				rwl.readLock().lock();
			}
		} finally {
			// 从新读取数据释放读锁
			value = cache.get(key);
			rwl.readLock().unlock();
		}
		return value;
	}
}
相关文章
相关标签/搜索