1

我有许多共享变量 x,y,z,所有这些都可以在两个不同线程中运行的两种不同方法中修改。(比如线程 1 中的方法 1 和线程 2 中的方法 2)。如果我将这两个方法声明为 synchronized ,是否保证变量 x,y 和 z 的一致性。或者我应该单独对每个变量使用锁定?

4

4 回答 4

2

是的,您的方法将保证一致性,假设这些变量都是私有的并且在两个同步方法之外不被访问(读取或写入)。

请注意,如果您在同步块之外读取这些变量,那么您可能会得到不一致的结果:

class Foo {
    private int x;

    public synchronized void foo() {
        x = 1;
    }

    public synchronized void bar() {
        x = 2;
    }

    public boolean baz() {
        int a = x;
        int b = x;
        // Unsafe! x could have been modified by another thread between the two reads
        // That means this method could sometimes return false
        return a == b;
    }
}

编辑:更新以解决您对静态变量的评论。

每个类都应该拥有自己的数据。如果类A允许直接访问变量(通过将其公开),那么它不拥有自己的数据,并且很难强制执行线程安全。

如果你这样做:

class A {
    private static int whatever;

    public static synchronized int getWhatever() {
        return whatever;
    }

    public static synchronized void setWhatever(int newWhatever) {
        whatever = newWhatever;
    }
}

那么你会没事的。

请记住,这synchronized会对单个对象强制执行互斥锁。对于同步方法,它是this(或静态方法的 Class 对象)。其他对象上的同步块不会干扰。

class A {
    public synchronized void doSomething() {...}
}
class B {
    public synchronized void doSomethingElse() {...}
}

调用doSomething不会等待调用,doSomethingElse因为它们在不同的对象上同步:在这种情况下,相关的实例AB. doSomething同样,对不同实例的两次调用A也不会干扰。

我强烈建议您看看Java Concurrency in Practice。这是一本很好的书,它解释了 Java 线程和内存模型的所有微妙之处。

于 2012-11-25T08:09:08.500 回答
1

是的,它将是一致的。

同步方法在执行之前获取监视器(第 17.1 节)。对于类(静态)方法,使用与方法类的 Class 对象关联的监视器。对于实例方法,使用与 this(调用该方法的对象)关联的监视器。

看看这个链接

注意:- 你必须小心的一点(一些程序员通常陷入这个陷阱)是同步的静态方法和同步的非静态方法之间没有联系

于 2012-11-25T08:10:09.717 回答
1

当您同步方法时:

  1. 如果 method 是static,将在class对象上获取锁
  2. 如果 method 是non-static,则将对该instance对象进行锁定。

只要锁一次只被一个线程占用,是的,做你想做的事情是一致且安全的。

于 2012-11-25T08:10:48.660 回答
0

这是主观的。行为取决于您实例化线程的方式。如果两个线程在包含这些方法的类的同一实例上调用同步化方法,它们将阻塞。如果每个线程实例化一个包含方法的类的新对象,它们将不会阻塞,因为在该类的两个不同实例上会有两个锁。

于 2012-11-25T08:17:00.400 回答