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

1、synchronized:它是java中的一个关键字,它可以把任意一个非NULL的对象当作锁。

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

2)当作用于静态方法时,锁住的是Class实例,又因为Class的相关数据存储在永久带PermGen(jdk1.8则是metaspace),永久带是全局共享的,因此静态方法锁相当于类的一个全局锁,会锁所有调用该方法的线程;

3)synchronized作用于一个对象实例时,锁住的是所有以该对象为锁的代码块。

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

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

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

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

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;
	}
}

转载于:https://my.oschina.net/u/3696939/blog/1831521

猜你喜欢

转载自blog.csdn.net/weixin_34253539/article/details/92400172