可能重复:
What is the difference between synchronized and static synchronized?
对象锁定类锁的优点是什么?
例如,
public static void log2(String msg1, String msg2){
synchronized(MyClass.class){
log.writeln(msg1);
log.writeln(msg2);
}
}
和
public void log2(String msg1, String msg2){
synchronized(this){
log.writeln(msg1);
log.writeln(msg2);
}
}
答案 0 :(得分:1)
如果在类上创建锁,则该类的所有实例将共享锁。如果您有1个实例,则不会有任何差异。如果您有数千个实例,它们都将使用完全相同的锁。如果许多线程同时尝试获取锁,它们将相互阻塞。在最坏的情况下,这可能会导致您的代码表现得好像根本没有线程。
如果在实例上创建锁,则只要多个线程在不同的实例上运行,就可以执行受保护的代码。这里,线程不会相互阻塞。所以这种方法表现更好。
但这不是你需要问的问题。真正的问题是:我需要什么样的锁?
如果要确保只有一个线程可以写入日志,则应在log
上进行同步。这种方法的另一个优点是,当您开始使用多个日志文件(例如,每个线程一个)时,它将自动正常工作。
答案 1 :(得分:0)
它们不可互换,因为它们锁定不同的物体。
如果锁定对象是合适的,请使用它。如果你想锁定一个类(这不太可能),你会使用它。
我会考虑这种组合。
public void log2(String msg1, String msg2){
synchronized(this) {
synchronized(log) {
log.writeln(msg1);
log.writeln(msg2);
}
}
}
这将确保不修改对象,并且行在日志中一起显示。
但是,由于log2似乎没有使用可变字段,您可以使用
private final Log log = ...
public void log2(String msg1, String msg2){
synchronized(log) {
log.writeln(msg1);
log.writeln(msg2);
}
}
答案 2 :(得分:0)
从下面给出的Logger类中,如果Log类被修改为使用Lock对象,则调用log(String msg1,String msg2)的线程将使用其新的同步策略对线程安全的日志执行操作。但是调用log(String msg1)方法的线程将始终在Log实例上同步,并且Log类中的所有Lock对象将一次保留。在这种情况下,Logger的实现会中断。这就是为什么建议使用私有的最终Lock对象或Lock类而不是客户端锁定。
public class Logger {
private final Log log;
private final Object lock = new Object();
public Logger(Log log) {
this.log = log;
}
public void log(String msg1) { // log synchronizes on log instance
synchronized (log) {
log.writeln(msg1);
}
}
public void log(String msg1, String msg2) { // log uses private final lock
synchronized (lock) {
log.writeln(msg1);
log.writeln(msg2);
}
}
}