有人能告诉我同步方法比同步块的优势与一个例子吗?
当前回答
关于使用同步块的重要提示:小心你使用的锁对象!
上面user2277816的代码片段说明了这一点,将字符串字面值的引用用作锁定对象。 意识到字符串字面值在Java中是自动互缩的,您应该开始看到问题所在:在字面值“锁”上同步的每段代码都共享同一个锁!这很容易导致完全不相关的代码段发生死锁。
您需要注意的不仅仅是String对象。装箱的原语也是一种危险,因为autoboxing和valueOf方法可以重用相同的对象,这取决于值。
有关更多信息,请参阅: https://www.securecoding.cert.org/confluence/display/java/LCK01-J.+Do+not+synchronize+on+objects+that+may+be+reused
其他回答
使用同步块,您可以有多个同步器,因此多个同时但不冲突的事情可以同时进行。
唯一真正的区别是同步块可以选择在哪个对象上同步。同步方法只能使用'this'(或同步类方法的相应Class实例)。例如,它们在语义上是等价的:
synchronized void foo() {
...
}
void foo() {
synchronized (this) {
...
}
}
后者更灵活,因为它可以竞争任何对象(通常是成员变量)的关联锁。它也更细粒度,因为您可以在块之前和块之后执行并发代码,但仍然在方法中。当然,您也可以通过将并发代码重构为单独的非同步方法来轻松地使用同步方法。使用任何使代码更容易理解的方法。
关于使用同步块的重要提示:小心你使用的锁对象!
上面user2277816的代码片段说明了这一点,将字符串字面值的引用用作锁定对象。 意识到字符串字面值在Java中是自动互缩的,您应该开始看到问题所在:在字面值“锁”上同步的每段代码都共享同一个锁!这很容易导致完全不相关的代码段发生死锁。
您需要注意的不仅仅是String对象。装箱的原语也是一种危险,因为autoboxing和valueOf方法可以重用相同的对象,这取决于值。
有关更多信息,请参阅: https://www.securecoding.cert.org/confluence/display/java/LCK01-J.+Do+not+synchronize+on+objects+that+may+be+reused
在同步方法的情况下,锁将在对象上获得。但是如果你使用同步块,你可以选择指定一个对象来获取锁。
例子:
Class Example {
String test = "abc";
// lock will be acquired on String test object.
synchronized (test) {
// do something
}
lock will be acquired on Example Object
public synchronized void testMethod() {
// do some thing
}
}
同步方法可以使用反射API进行检查。这对于测试某些契约很有用,比如模型中的所有方法都是同步的。
下面的代码段打印哈希表的所有同步方法:
for (Method m : Hashtable.class.getMethods()) {
if (Modifier.isSynchronized(m.getModifiers())) {
System.out.println(m);
}
}
推荐文章
- 在流中使用Java 8 foreach循环移动到下一项
- 访问限制:'Application'类型不是API(必需库rt.jar的限制)
- 用Java计算两个日期之间的天数
- 如何配置slf4j-simple
- 在Jar文件中运行类
- 带参数的可运行?
- 自动化invokerrequired代码模式
- 我如何得到一个字符串的前n个字符而不检查大小或出界?
- 我可以在Java中设置enum起始值吗?
- Java中的回调函数
- c#和Java中的泛型有什么不同?和模板在c++ ?
- 在Java中,流相对于循环的优势是什么?
- Jersey在未找到InjectionManagerFactory时停止工作
- 在Java流是peek真的只是调试?
- Recyclerview不调用onCreateViewHolder