lock和synchronized的区别

69 篇文章 1 订阅
55 篇文章 3 订阅

lock和synchronized的区别

lock和synchronized的区别

一直以来java有很多的相似关键字或相似意义的字,不是很好区别和掌握,下边来说下这两个单词在Java中的基本概念和应用,我这个也是收百家之长来汇总的。

相同点

synchronized和lock都是锁的意思,都是为了线程安全性,
应用合理性和运行效率的。

可以简单理解lock比前置更加优秀和合理,是前者
的优化版。

不同点

主要还是来说说其不同点。


- 一 synchronized在Java中是关键字,有其语言的内置性。 lock则不是java的关键字,它是Java的一个接口类。


- 二 被synchronized修饰的代码块会自动释放锁,而lock则需要手动的释放。

拓展:lock如果没有手动释放锁标记,就有可能出现死锁的现象。

什么是死锁:
是指两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程。

死锁的四个必要条件:
1 互斥条件:一个资源每次只能被一个进程使用;
2 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放;
3 不剥夺条件:进程已获得的资源,在末使用完之前,不能强行剥夺;
4 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系;
   
   
*synchronized释放锁的两种时机:
1 获取锁的线程执行完代码块,释放对锁的占有。
2 线程发生异常,JVM会让线程自动释放锁。

*lock释放锁:    
ReentrantLock加锁(lock())、释放锁(unlock())

**

解释说明:

**

有了synchronized关键字,为什么还需要lock这个接口类呢?

synchronized的不足:

1 如果获取锁的线程等待被执行的代码块是被阻塞了(调用了sleep方法/等待IO或其它原因),但是没有释放锁,那么这个线程只能等着代码块被执行完,这样在效率上和用户体验上都是很差的。

2 还有就是多线程写文章时,读操作和写操作会发生冲突现象,写操作和写操作也会发生冲突现象,但是读操作和读操作是不会发生冲突现象的,而你用了synchronized锁来实现同步的话两个读操作也会发生冲突,这样是不合理的。

为了解决这两种或者其它的有关问题就可以使用lock来实现。

lock的方法是用和说明:

void lock()获取锁
如果锁不可用,出于线程调度目的,将禁用当前线程,并且在获得锁之前,该线程将一直处于休眠状态。

实现注意事项

Lock 实现可能能够检测到锁的错误使用,比如会导致死锁的调用,在那种环境下还可能抛出一个 (unchecked) 异常。Lock 实现必须对环境和异常类型进行记录。

lockInterruptibly
void lockInterruptibly()
throws InterruptedException如果当前线程未被中断,则获取锁。
如果锁可用,则获取锁,并立即返回。

如果锁不可用,出于线程调度目的,将禁用当前线程,并且在发生以下两种情况之一以前,该线程将一直处于休眠状态:

锁由当前线程获得;或者
其他某个线程中断当前线程,并且支持对锁获取的中断。
如果当前线程:

在进入此方法时已经设置了该线程的中断状态;或者
在获取锁时被中断,并且支持对锁获取的中断,
则将抛出 InterruptedException,并清除当前线程的已中断状态。
实现注意事项

在某些实现中可能无法中断锁获取,即使可能,该操作的开销也很大。程序员应该知道可能会发生这种情况。在这种情况下,该实现应该对此进行记录。

相对于普通方法返回而言,实现可能更喜欢响应某个中断。

Lock 实现可能可以检测锁的错误用法,例如,某个调用可能导致死锁,在特定的环境中可能抛出(未经检查的)异常。该 Lock 实现必须对环境和异常类型进行记录。

抛出:
InterruptedException - 如果在获取锁时,当前线程被中断(并且支持对锁获取的中断)。

tryLock
boolean tryLock()仅在调用时锁为空闲状态才获取该锁。
如果锁可用,则获取锁,并立即返回值 true。如果锁不可用,则此方法将立即返回值 false。

此方法的典型使用语句如下:

  Lock lock = ...;
  if (lock.tryLock()) {
      try {
          // manipulate protected state
      } finally {
          lock.unlock();
      }
  } else {
      // perform alternative actions
  }

此用法可确保如果获取了锁,则会释放锁,如果未获取锁,则不会试图将其释放。

返回:
如果获取了锁,则返回 true;否则返回 false。

tryLock
boolean tryLock(long time,
TimeUnit unit)
throws InterruptedException如果锁在给定的等待时间内空闲,并且当前线程未被中断,则获取锁。
如果锁可用,则此方法将立即返回值 true。如果锁不可用,出于线程调度目的,将禁用当前线程,并且在发生以下三种情况之一前,该线程将一直处于休眠状态:

锁由当前线程获得;或者
其他某个线程中断当前线程,并且支持对锁获取的中断;或者
已超过指定的等待时间
如果获得了锁,则返回值 true。

如果当前线程:

在进入此方法时已经设置了该线程的中断状态;或者
在获取锁时被中断,并且支持对锁获取的中断,
则将抛出 InterruptedException,并会清除当前线程的已中断状态。
如果超过了指定的等待时间,则将返回值 false。如果 time 小于等于 0,该方法将完全不等待。

实现注意事项

在某些实现中可能无法中断锁获取,即使可能,该操作的开销也很大。程序员应该知道可能会发生这种情况。在这种情况下,该实现应该对此进行记录。

相对于普通方法返回而言,实现可能更喜欢响应某个中断,或者报告出现超时情况。

Lock 实现可能可以检测锁的错误用法,例如,某个调用可能导致死锁,在特定的环境中可能抛出(未经检查的)异常。该 Lock 实现必须对环境和异常类型进行记录。

参数:
time - 等待锁的最长时间
unit - time 参数的时间单位
返回:
如果获得了锁,则返回 true;如果在获取锁前超过了等待时间,则返回 false
抛出:
InterruptedException - 如果在获取锁时,当前线程被中断(并且支持对锁获取的中断)

unlock
void unlock()释放锁。
实现注意事项

Lock 实现通常对哪个线程可以释放锁施加了限制(通常只有锁的保持者可以释放它),如果违背了这个限制,可能会抛出(未经检查的)异常。该 Lock 实现必须对所有限制和异常类型进行记录。

newCondition
Condition newCondition()返回绑定到此 Lock 实例的新 Condition 实例。
在等待条件前,锁必须由当前线程保持。调用 Condition.await() 将在等待前以原子方式释放锁,并在等待返回前重新获取锁。

实现注意事项

Condition 实例的具体操作依赖于 Lock 实现,并且该实现必须对此加以记录。

返回:
用于此 Lock 实例的新 Condition 实例
抛出:
UnsupportedOperationException - 如果此 Lock 实现不支持条件

链接: https://mp.csdn.net/mdeditor#(https://mp.csdn.net).

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值