锁
来源:互联网 发布:java实体是什么 编辑:程序博客网 时间:2024/04/29 15:15
锁
一,基本概念
节约篇幅,锁(Lock)是什么就不说了,先列出几个重要的概念。
锁级别:分为对象级和类级,常见的大部分锁是对象锁;所有(或者绝大部分)的类和对象都自带一把隐藏的锁,这也是synchronized能锁任意对象和类的根本所在。每个对象有自己的对象锁,所有对象共用一个类锁。
可重入性:假设条件:锁住的方法中调用另一个锁住的方法,且两个锁是同一个对象。结果:如果该锁具有可重入性,则自动识别放行,常见的大部分锁都是这种类型;如果该锁不具备可重入性,则产生死锁。
互斥和非互斥:互斥就是同一时刻只能有一个线程访问,常见的大部分锁都是这种类型;非互斥就是(!互斥),比如读写锁(ReadWriteLock)能支持多个线程同时读,就不是互斥锁。
公平和非公平:公平就是遵循先到先得(FIFO)的原则,非公平则竞争获取,看cpu的心情。
二,体系结构
需要注意的是,Lock和ReadWriteLock是两个不同的接口,对应两个不种不同的体系结构。ReadWriteLock的JDK实现类ReentrantReadWriteLock内置一个ReadLock和一个WriteLock。非重入性的锁我从JDK1.7以及网络都没找到,以后遇到再补充,也希望高手补充下。
三,常见实例
关于synchronized:
Lock其实是一个独立的概念,但是在简单的应用中我们常常使用synchronized关键字来解决对象多线程同步访问的问题。synchronized可以锁整个方法,也可以锁某个小范围的过程。
public class SynTest{// 对象级别锁,锁住当前对象,也就是thispublic synchronized void syn1(){// do something}// 类级别锁,锁住当前对象的类,也就是SynTest.classpublic synchronized static void syn2(){// do something}// 对象级别锁,锁住当前对象,也就是thispublic 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}}// 对象级别锁,锁住当前对象,也就是thispublic synchronized void syn6(){// 线程运行到这里的时候,this对象把锁交给该线程,syn1要求获取this锁才行运营,this锁具有可重入性,所以syn1也可以执行syn1();}}
synchronized其实是一种隐式的上锁,本质上也是对Lock的操作,只需要理解到底是哪个对象被锁住了即可。
自定义锁:
synchronized提供了一种便捷的上锁方式,我们有时候还会自定义锁对象,因为自定义锁对象的一些高级特性是synchronized无法拥有的,而且应用更灵活。这里主要介绍ReentrantLock和ReentrantReadWriteLock。
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();}}}
- 锁
- 锁
- 锁
- 锁
- 锁
- 锁
- 锁
- 锁
- 锁
- 锁
- 锁
- 锁
- 锁
- 锁
- 锁
- 锁
- 锁
- 锁
- AC自动机
- Matlab 脚本编译成dll被c++调用
- TextView属性大全
- (六)原型模式
- 计算机网络总结笔记
- 锁
- vmware Tools 全系列版本下载及安装方法(vmware Tools 10~12)
- linux read
- #和##在宏中的妙用
- USB集腋成裘:从Linux PC角度看sys.usb.config为none时的Android设备
- 拿到一份开源项目,快速定位感兴趣的功能代码
- 3.关于removeFromSuperview和addSubview
- Oracle中的char,varchar,varchar2,nvarchar,nvarchar2的比较
- 【infoQ】物联网项目的网络注意事项