多线程-锁(Lock)

锁的分类

1,公平锁/非公平锁
公平锁是指线程按照申请顺序获得锁。如果休眠队列上有线程了,那新进入的竞争线程一定要在休眠队列上排队。
非公平锁是指线程能够无视休眠队列,直接竞争锁,使后申请的线程可能先占有锁。可能会导致优先级反转或者饥饿现象。非公平锁的优点在于吞吐量比公平锁大。
对于Java ReetrantLock而言,通过构造函数指定该锁是公平锁,默认是非公平锁。
2,可重入锁
又名递归锁。是指在同一个线程在外层方法获取锁的时候,进入内层会自动获取锁,sychronized和Java ReetrantLock都是可冲入锁。可重入锁可在一定程度上避免死锁。

3,独享锁/共享锁
独享锁一次只能被一个线程占据,共享锁可以杯多个线程持有。
4,自旋锁
锁的等待者会原地忙等,不停地询问,直到获得锁。采用让当前线程不停的在循环体内执行实现,当循环条件被其它线程改变时才能进入临界曲。

lock与sychronized

1,sychronized底层实现原理
对象的同步sychronized是通过monioer来完成的
每一个监视器(monitor)。当monitor被占用就会处于锁定状态,线程执行monitorenter指令时尝试获取monitor所有权,过程如下:
(1)如果monitor的进入数是0,则线程进入moniter,然后进入数加1,该线程为moniter的所有者;
(2)如果该线程已经占有monitor,只是重新进入,则进入moniter的进入数加1;
(3)如果其它线程已经占有了monitor,则线程进入阻塞状态,知道monitor的进入人数为0,再重新尝试获取monitor的所有权。
释放锁是通过monitorexit指令,执行monitorexit的线程必须是objectref对应的monitor的所有者,monitor进入数据减1,如果减1后数为0,那线程退出方法的sychronized同步。
相对于普通方法,其常亮池中多了ACC_SYCHRONIZED标示符。JVM就是根据改标识符来实现方法同步的;当方法调用时,调用指令将会检查该方法的ACC_SYCHRONIZED访问标识符是否被设置了,如果设置了,执行线程将先获取monitor,获取成功后才能执行方法体。在方法执行器件,其他任何线程都无法再获得同一个monitor对象。
2,Lock对象的使用

对于Lock对象的使用主要设计两个实现类:ReentrantLock类,ReentrantReadWriteLock类。
(1)ReentrantLock的使用

private Lock lock = new ReentrantLock();
public void testMethod(){
lock.lock();
.......
lock.unlock();
}

(2)ReentrantLock底层实现原理
整体来看Lock主要是通过两个东西来实现的分别是CAS和ASQ,如下:
• AQS维护了一个volatile int state(代表共享资源)和一个FIFO线程等待队列(多线程争用资源被阻塞时会进入此队列)。
• 对于刚来竞争的线程首先会通过CAS设置状态,如果设置成功那么直接获取锁,执行临界区的代码;
• 反之如果已经存在Running线程,那么CAS肯定会失败,则新的竞争线程会通过CAS的方式被追加到队尾。
以ReentrantLock为例,state初始化为0,表示未锁定状态。A线程lock()时,会调用tryAcquire()独占该锁并将state+1。此后,其他线程再tryAcquire()时就会失败,直到A线程unlock()到state=0(即释放锁)为止,其它线程才有机会获取该锁。当然,释放锁之前,A线程自己是可以重复获取此锁的(state会累加),这就是可重入的概念。但要注意,获取多少次就要释放多么次,这样才能保证state是能回到零态的。

3,Lock与sychronized的比较
Lock可以让等待线程只等待一定时间或者响应中断,Sychronized则是无限等待下去;
Lock可以让多个线程只是进行读操作的时候共享锁,Sychronized则是一个线程读操作时,其它线程只能等待;
Lock可以知道线程有没有成功获取到锁,Sychronized则不行。
Lock必须手动释放锁,不能主动释放锁,就有可能导致出现死锁现象,因此使用Lock时需要在finally中释放锁。而sychroonized发生异常时会自动释放线程占有锁,因此不会导致死锁发生。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值