synchronized 和java.util.concurrent.locks.Lock的异同

来源:互联网 发布:mac的关闭快捷键 编辑:程序博客网 时间:2024/06/05 19:26

Lock是Java 5以后引入的新的API,和关键字synchronized相比主要相同点:Lock 能完成synchronized所实现的所有功能;主要不同点:Lock有比synchronized更精确的线程语义和更好的性能,而且不强制性的要求一定要获得锁。synchronized会自动释放锁,而Lock一定要求程序员手工释放,并且最好在finally 块中释放(这是释放外部资源的最好的地方)。如果不释放,可能会引起难以预料的后果(在多线程环境中)。

注意:lock 必须在 finally 块中释放。否则,如果受保护的代码将抛出异常,锁就有可能永远得不到释放

 1.当代码块 加上 synchrozized之后,代码会发生什么改变?

    答案:有两条改变。一个是原子性(atomicity),一个是可见性(visibility)。原子性意味着一次只能有一个线程获得代码锁,进入synchronized 包围的代码块中执行。而可见性则是对不同范围内对变量的修改做出的一致性。强调变量的可见性与一致性,是因为在Java 内存中,内存缓存和编译器优化在多线程条件下会造成各种反常行为。一般来说,线程以某种不必让其他线程立即可以看到的方式(不管这些线程在寄存器(register)中、在处理器特定的缓存(CPU cache)中,还是通过指令重排或者其他编译器优化),不受缓存变量值的约束,但是加人synchronized关键字之后,那么运行库将确保某一线程对变量所做的更新先于对现有 synchronized 块所进行的更新,当进入由同一监控器(lock)保护的另一个 synchronized 块时,将立刻可以看到这些对变量所做的更新。类似的规则也存在于 volatile 变量

  2. 为什么需要java.util.concurrent.lock?

  主要是synchronized是比较古老的实现机制,设计较早,有一些功能上的限制:
—— 它无法中断一个正在等候获得锁的线程
——也无法通过投票得到锁,如果不想等下去,也就没法得到锁。
——同步还要求锁的释放只能在与获得锁所在的堆栈帧相同的堆栈帧中进行

 3. 重入锁 ReentrantLock


java.util.concurrent.lock 中的 Lock 框架是锁定的一个抽象,它允许把锁定的实现作为 Java 类,而不是作为语言的特性来实现。
这就为 Lock 的多种实现留下了空间,各种实现可能有不同的调度算法、性能特性或者锁定语义。 
ReentrantLock 类实现了Lock ,它拥有与 synchronized 相同的并发性和内存语义,但是添加了类似锁投票、定时锁等候和可中断锁等候的一些特性。
此外,它还提供了在激烈争用情况下更佳的性能。(换句话说,当许多线程都想访问共享资源时,JVM 可以花更少的时候来调度线程,把更多时间用在执行线程上。



阅读全文
0 0
原创粉丝点击