0

可能重复:
同步和静态同步有什么区别?

对象锁优于类锁有什么优势?

例如,

 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);
       }
    }
4

3 回答 3

1

如果您在类上创建锁,则该类的所有实例都将共享该锁。如果您有 1 个实例,则不会有任何区别。如果您有数千个实例,它们都将使用相同的锁。如果多个线程同时尝试获取锁,它们会相互阻塞。在最坏的情况下,这可能会导致您的代码表现得好像根本没有线程一样。

如果您在实例上创建锁,那么多个线程可以执行受保护的代码,只要它们在不同的实例上操作。在这里,线程不会相互阻塞。所以这种方法效果更好。

但这不是你需要问的。真正的问题是:我需要什么样的锁?

如果要确保只有单个线程可以写入日志,则应在log. 这种方法还有一个额外的优势,即当您开始使用多个日志文件(例如,每个线程一个)时,它会自动正常工作。

于 2012-10-15T12:05:47.380 回答
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);
    }
}
于 2012-10-15T11:48:03.207 回答
0

从下面给出的 Logger 类中,如果 Log 类被修改为使用 Lock 对象,则调用 log(String msg1, String msg2) 的线程将使用其新的同步策略对线程安全 Log 执行操作。但是调用 log(String msg1) 方法的线程将始终在 Log 实例上同步,并且 Log 类中的所有 Lock 对象将同时被持有。在这种情况下,Logger 的实现会中断。这就是为什么建议使用私有 final 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);  
        }
    }   
}
于 2012-10-16T02:33:27.680 回答