Lock和Synchronized

1 锁的分类

可重入锁

Synchronized和ReentrantLook都是可重入锁,锁的可重入性标明了锁是针对线程分配方式而不是针对方法。例如调用Synchronized方法A中可以调用Synchronized方法B,而不需要重新申请锁。

读写锁

按照数据库事务隔离特性的类比读写锁,在访问统一个资源(一个文件)的时候,使用读锁来保证多线程可以同步读取资源。ReadWriteLock是一个读写锁,通过readLock()获取读锁,通过writeLock()获取写锁。

可中断锁

可中断是指锁是可以被中断的,内置锁是不可中断锁,ReentrantLock可以通过lockInterruptibly方法中断显性锁。例如线程B在等待等待线程A释放锁,但是线程B由于等待时间太久,可以主动中断等待锁

公平锁

公平锁:公平锁是指尽量以线程的等待时间先后顺序获取锁,等待时间最久的线程优先获取锁。synchronized隐性锁是非公平锁,它无法保证等待的线程获取锁的顺序,ReentrantLook可以自己控制是否公平锁

2 synchronized的缺陷

如果一个代码块被synchronized修饰,当一个线程获取了对应的锁,并执行代码块时,其他线程只能一直等待,等待获取锁的线程释放锁,而这里获取锁的线程释放锁只会有两种情况

无期限地等待

如果这个获取锁的线程由于要等待IO或者其他原因(比如调用sleep方法)被阻塞了,但是又没有释放锁,其他线程便只能干巴巴地等待,试想一下,这多么影响程序执行效率。

因此就需要有一种机制可以不让等待的线程一直无期限地等待下去(比如只等待一定的时间或者能够响应中断),通过Lock就可以办到( lockInterruptibly)

读等待

当有多个线程读写文件时,读操作和写操作会发生冲突现象,写操作和写操作会发生冲突现象,但是读操作和读操作不会发生冲突现象。

因此就需要一种机制来使得多个线程都只是进行读操作时,线程之间不会发生冲突,通过Lock就可以办到(读写锁)

3 区别

关键字和接口类

Synchronized是关键字,内置语言实现,Lock是接口。

自动释放(出现异常自动释放)和手动释放(需要finally)

Synchronized在线程发生异常时会自动释放锁,因此不会发生异常死锁(但其它情况也会出现)。Lock异常时不会自动释放锁,所以需要在finally中实现释放锁。

可中断和状态查询

Lock是可以中断锁,Synchronized是非中断锁,必须等待线程执行完成释放锁。另外通过Lock可以知道有没有成功获取锁(isHeldByCurrentThread和tryLock),而synchronized却无法办到

读写锁

ReentrantReadWriteLock实现了ReadWriteLock接口(非Lock),Lock可以使用读锁提高多线程读效率。
读写、写写、写读互斥:如果有一个线程已经占用了读锁,则此时其他线程如果要申请写锁,则申请写锁的线程会一直等待释放读锁。如果有一个线程已经占用了写锁,则此时其他线程如果申请写锁或者读锁,则申请的线程会一直等待释放写锁。

选择性通知(多路通知)

就是在一个Lock对象中可以创建多个Condition实例(即对象监视器),线程对象可以注册在指定的Condition中,从而可以有选择性的进行线程通知,在调度线程上更加灵活。

具有一个同步队列,多个等待队列,可以让某些线程在合适的时间等待,或在某一时刻得到通知继续执行。而Synchronized相当于只有一个同步队列和一个等待队列。

4 使用Lock的注意事项

需要将lock声明为类的属性,不能是局部变量;
单独调用interrupt()方法不能中断正在运行过程中的线程,只能中断阻塞过程中的线程。

.

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值