一,基本概念

节约篇幅,锁(Lock)是什么就不说了,先列出几个重要的概念。

锁级别:分为对象级和类级,常见的大部分锁是对象锁;所有(或者绝大部分)的类和对象都自带一把隐藏的锁,这也是synchronized能锁任意对象和类的根本所在。每个对象有自己的对象锁,所有对象共用一个类锁。

可重入性:假设条件:锁住的方法中调用另一个锁住的方法,且两个锁是同一个对象。结果:如果该锁具有可重入性,则自动识别放行,常见的大部分锁都是这种类型;如果该锁不具备可重入性,则产生死锁。

互斥和非互斥:互斥就是同一时刻只能有一个线程访问,常见的大部分锁都是这种类型;非互斥就是(!互斥),比如读写锁(ReadWriteLock)能支持多个线程同时读,就不是互斥锁。

公平和非公平:公平就是遵循先到先得(FIFO)的原则,非公平则竞争获取,看cpu的心情。


二,体系结构


需要注意的是,LockReadWriteLock是两个不同的接口,对应两个不种不同的体系结构。ReadWriteLockJDK实现类ReentrantReadWriteLock内置一个ReadLock和一个WriteLock。非重入性的锁我从JDK1.7以及网络都没找到,以后遇到再补充,也希望高手补充下。


三,常见实例

关于synchronized

Lock其实是一个独立的概念,但是在简单的应用中我们常常使用synchronized关键字来解决对象多线程同步访问的问题。synchronized可以锁整个方法,也可以锁某个小范围的过程。

public class SynTest
{
	// 对象级别锁,锁住当前对象,也就是this
	public synchronized void syn1(){
		// do something
	}
	
	// 类级别锁,锁住当前对象的类,也就是SynTest.class
	public synchronized static void syn2(){
		// do something
	}
	
	// 对象级别锁,锁住当前对象,也就是this
	public void syn3(){
		synchronized(this)
		{
			// do something
		}
	}
	
	// 对象级别锁,锁住list实例
	public void syn4(){
		List<String> list = new ArrayList<String>();
		synchronized(list)
		{
			// do something
		}
	}
	
	// 类级别锁,锁住SynTest.class,跟syn2()一样
	public void syn5(){
		synchronized(SynTest.class)
		{
			// do something
		}
	}
	
	// 对象级别锁,锁住当前对象,也就是this
	public synchronized void syn6(){
		// 线程运行到这里的时候,this对象把锁交给该线程,syn1要求获取this锁才行运营,this锁具有可重入性,所以syn1也可以执行
		syn1();
	}
}

synchronized其实是一种隐式的上锁,本质上也是对Lock的操作,只需要理解到底是哪个对象被锁住了即可。

自定义锁:

synchronized提供了一种便捷的上锁方式,我们有时候还会自定义锁对象,因为自定义锁对象的一些高级特性是synchronized无法拥有的,而且应用更灵活。这里主要介绍ReentrantLockReentrantReadWriteLock

ReentrantLock:

结合我遇到的实际情况来说明吧,我们有一个场景是对线路做监控,如果线路调度连续失败的次数超过一定的阀值(基本都是该线路失联了),则智能切换到其他线路。代码结构如下,可以看到tryLock方法不阻塞其他线程的特性。

public class Watcher
{
	private static final int ERROR_THRESHOLD = 100;
	private static Integer failCount = 0;
	private static ReentrantLock lock = new ReentrantLock();
	
	// 失败次数递增
	public static void add()
	{
		synchronized(failCount)
		{
			failCount++;
		}
		if(failCount > ERROR_THRESHOLD)// 连续失败次数大于切换阀值
		{
			lock.tryLock();
			try
			{
				// 只能有一个线程执行切换,切换代码省略
			}catch(Exception e)
			{
				e.printStackTrace();
			}finally
			{
				lock.unlock();
			}
			
		}
	}
	
	// 失败次数重置
	public static void reset()
	{
		synchronized(failCount)
		{
			failCount = 0;
		}
	}
}

ReentrantReadWriteLock:

这个是一个非互斥锁,特性是只能有一个线程可以写,写的时候不能读,读的时候不能写,读的时候还能读。看到这个特性,就知道它是为操作一些需要常常读取,但是很少需要修改的数据而定制的。从我实际遇到的情况来说,就是关键字过滤功能,关键字库一般初始化好放内存中,只在很少的情况下需要去修改这个内存。

public class KeywordService
{
	private static ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
	
	// 关键字匹配
	public static void matchKeyword(String msg)
	{
		
		lock.readLock().lock();
		try
		{
			// 执行匹配
		}catch(Exception e)
		{
			e.printStackTrace();
		}finally
		{
			lock.readLock().unlock();
		}
	}
	
	// 重置关键字到内存
	public static void reloadKeyword()
	{
		lock.writeLock().lock();
		try
		{
			// 重载关键字到内存
		}catch(Exception e)
		{
			e.printStackTrace();
		}finally
		{
			lock.writeLock().unlock();
		}
	}
}






  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值