繁体   English   中英

Java同步方法

[英]Java Synchronized Methods

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

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

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

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因为它们在不同的对象上同步:在这种情况下, A的相关实例和B的相关实例。 同样,在A不同实例上对doSomething两次调用不会干扰。

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

是的,这将是一致的。

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

看看这个链接

注意: - 你需要注意的一点(一些程序员通常属于那个陷阱)是同步静态方法和同步非静态方法之间没有联系

在同步方法时:

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

只要一次只能通过一个线程进行锁定,是的,按照您的意图进行操作是一致和安全的。

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM