【发布时间】:2012-01-30 23:39:11
【问题描述】:
我在 Java 中使用过 synchronized 关键字和重入锁,但我不明白它们有何不同,或者哪种适合特定情况。
我如何决定什么时候应该使用synchronized,什么时候应该使用重入锁?
【问题讨论】:
标签: java thread-safety
我在 Java 中使用过 synchronized 关键字和重入锁,但我不明白它们有何不同,或者哪种适合特定情况。
我如何决定什么时候应该使用synchronized,什么时候应该使用重入锁?
【问题讨论】:
标签: java thread-safety
具有相同基本行为的可重入互斥锁和 语义作为使用同步访问的隐式监视器锁 方法和语句,但具有扩展功能。
扩展功能包括:
“[公平] 锁有利于授予对等待时间最长的线程的访问权限。否则此锁不保证任何特定的访问顺序。”
可重入锁的缺点是:
synchronized 关键字可以放在方法定义中,从而避免需要减少嵌套的块。总结
synchronized 关键字在语法上更好,但可重入锁具有更多功能。
【讨论】:
这个网站清楚地提到了 ReentrantLock 和 Java 中的 synchronized 关键字之间的区别。我只是从那里复制和粘贴。
1) ReentrantLock 和 synchronized 关键字的另一个显着区别是公平性。 synchronized 关键字不支持公平。任何线程一旦释放就可以获取锁,不能指定偏好,另一方面可以通过指定公平属性使 ReentrantLock 公平,同时创建 ReentrantLock 的实例。 Fairness 属性为最长等待线程提供锁,以防发生争用。
2) 同步锁和可重入锁的第二个区别是 tryLock() 方法。 ReentrantLock 提供了方便的 tryLock() 方法,该方法仅在其可用或未被任何其他线程持有时才获取锁。这减少了在 Java 应用程序中等待锁定的线程阻塞。
3) ReentrantLock 和 Java 中的 synchronized 关键字之间另一个值得注意的区别是,可以在等待 Lock 时中断线程。在 synchronized 关键字的情况下,线程可以无限期地阻塞等待锁定,并且无法控制。 ReentrantLock 提供了一个名为 lockInterruptibly() 的方法,可以用来在线程等待锁时中断线程。类似地,如果在某个时间段内锁不可用,可以使用带超时的 tryLock() 来超时。
4) ReentrantLock 还提供了方便的方法来获取所有等待锁的线程列表。
【讨论】:
我一直认为同步是“阻力最小的黑客”。它只是工作,大多数人都理解它是如何工作的,但它有一些弱点可能会影响你在高并发下的设计。其中最重要的是,任何客户端都可以有效地直接访问对象的同步锁,这意味着如果他们抓住它并持有它,其他客户端不能。换句话说,默认同步实现的锁定有效地“发布”了对象的内部锁定机制。玉。这就像为自己造成的拒绝服务做好准备。
如果你在你的类内部设置了可重入锁(或者只是不使用同步,而是在你想要同步的任何地方在你的构造函数中新建的一些内部对象上进行同步),你删除这个边-发布内部锁定机制的影响,随着类的发展,您必须记住在哪里应用这种内部同步,这增加了复杂性。
【讨论】:
synchronized 修饰符应用于可访问的方法时,而不是在不可访问的锁对象上使用 synchronized 块时。