有什么理由不到处打“同步”关键字?

2022-09-04 23:40:41

在我的java项目中,我写的几乎每个非静态方法都是.我决定通过删除大多数关键字来修复一些代码。就在那里,我创建了几个线程问题,这些问题需要很长时间才能修复,并且没有提高性能。最后,我恢复了一切。synchronizedsynchronized

我没有看到其他人到处都用“”编写代码。那么有什么理由我不应该在任何地方都有“”呢?synchronizedsynchronized

如果我不太关心性能(即,该方法不会每隔几秒钟调用一次以上)怎么办?


答案 1

如果不加选择地进行同步,则还存在创建死锁的风险。

假设我有两个类,并且 ,它们都有一个同步方法。进一步假设每个类都有一个同步方法,将另一个类的实例作为参数。FooBardoSomething()

public class Foo {

    synchronized void doSomething() {
        //code to doSomething
    }

    synchronized void doSomethingWithBar(Bar b) {
        b.doSomething();
    }

}

public class Bar {

    synchronized void doSomething() {
        //code to doSomething
    }

    synchronized void doSomethingWithFoo(Foo f) {
        f.doSomething();
    }
}

您可以看到,如果您有 一个 实例和 一个 实例,两者都尝试同时对彼此执行它们的方法,则可能会发生死锁。FooBardoSomethingWith*

要强制死锁,您可以在这两种方法中插入 sleep(用作示例):doSomethingWith*Foo

synchronized void doSomethingWithBar(Bar b) {
    try {
        Thread.sleep(10000);
    } catch (InterruptedException ie) {
        ie.printStackTrace();
    }

    b.doSomething();
}

在 main 方法中,启动两个线程来完成该示例:

public static void main(String[] args) {
    final Foo f = new Foo();
    final Bar b = new Bar();
    new Thread(new Runnable() {
        public void run() {
            f.doSomethingWithBar(b);
        }
    }).start();

    new Thread(new Runnable() {
        public void run() {
            b.doSomethingWithFoo(f);
        }
    }).start();
}

答案 2

当然 - 性能。显示器是有成本的。

答案既不是以随机方式删除同步,也不是以随机方式添加同步。最好阅读Brian Goetz的“Java Concurrency In Practice”或Doug Lea的“Java Threads”书籍,以了解如何正确做到这一点。当然,还要好好学习新的并发包。

多线程处理比同步关键字要多得多。