简体   繁体   English

Java同步方法

[英]Java Synchronized Methods

I have a number of shared variable x,y,z, all of which can modified in two different methods running in two different threads.(say method 1 in thread 1 and method 2 in thread 2) . 我有一些共享变量x,y,z,所有这些变量都可以在两个不同的线程中运行两种不同的方法进行修改。(比如线程1中的方法1和线程2中的方法2)。 If I declare these two methods as synchronized , does it guarantee the consistency of the variables x,y and z. 如果我将这两个方法声明为synchronized,它是否保证变量x,y和z的一致性。 Or should I separately use a lock on each of those variables? 或者我应该在每个变量上单独使用锁?

Yes, your approach will guarantee consistency, assuming those variables are all private and are not accessed (read or write) outside of the two synchronized methods. 是的,您的方法将保证一致性,假设这些变量都是私有的,并且在两个同步方法之外不被访问(读取或写入)。

Note that if you read those variables outside of a synchronized block then you could get inconsistent results: 请注意,如果您在同步块之外读取这些变量,那么您可能会得到不一致的结果:

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

EDIT: Updated to address your comment about the static variable. 编辑:更新以解决您对静态变量的评论。

Each class should own its own data. 每个类都应该拥有自己的数据。 If class A allows direct access to a variable (by making it public) then it is not owning its own data and it becomes very difficult to enforce thread safety. 如果A类允许直接访问变量(通过使其公开),那么它不拥有自己的数据,并且实现线程安全变得非常困难。

If you do this: 如果你这样做:

class A {
    private static int whatever;

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

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

then you'll be fine. 那你就没事了。

Remember that synchronized enforces a mutex on a single object. 请记住, synchronized在单个对象上强制执行互斥锁。 For synchronized methods it's this (or the Class object for static methods). 对于同步方法,它就是this (或静态方法的Class对象)。 Synchronized blocks on other objects will not interfere. 其他对象上的同步块不会干扰。

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

A call to doSomething will not wait for calls to doSomethingElse because they're synchronized on different objects: in this case, the relevant instance of A and the relevant instance of B . doSomething的调用不会等待调用doSomethingElse因为它们在不同的对象上同步:在这种情况下, A的相关实例和B的相关实例。 Similarly, two calls to doSomething on different instances of A will not interfere. 同样,在A不同实例上对doSomething两次调用不会干扰。

I highly recommend that you take a look at Java Concurrency in Practice . 我强烈建议您查看Java Concurrency in Practice It is an excellent book that explains all the subtleties of the Java thread and memory models. 这是一本很好的书,解释了Java线程和内存模型的所有细微之处。

Yes it will be consistent. 是的,这将是一致的。

A synchronized method acquires a monitor (§17.1) before it executes. 同步方法在执行之前获取监视器(第17.1节)。 For a class (static) method, the monitor associated with the Class object for the method's class is used. 对于类(静态)方法,使用与方法类的Class对象关联的监视器。 For an instance method, the monitor associated with this (the object for which the method was invoked) is used. 对于实例方法,使用与此关联的监视器(调用该方法的对象)。

Check out this link 看看这个链接

Note:- One point you have to be careful about (several programmers generally fall in that trap) is that there is no link between synchronized static methods and sync'ed non static methods 注意: - 你需要注意的一点(一些程序员通常属于那个陷阱)是同步静态方法和同步非静态方法之间没有联系

When you synchronize on methods : 在同步方法时:

  1. If method is static , the lock will be taken on the class object 如果method是static ,则将对class对象进行锁定
  2. If method is non-static , the lock will be taken on the instance object. 如果method non-static ,则将对instance对象进行锁定。

As long as the lock is taken only by one thread at one time, yes it is consistent and safe to do what you intend to. 只要一次只能通过一个线程进行锁定,是的,按照您的意图进行操作是一致和安全的。

This is subjective. 这是主观的。 The behaviour depends on the way you instantiate your threads. 行为取决于您实例化线程的方式。 If two threads call the synchtonized methods on the same instance of the class containing these methods, they will block. 如果两个线程在包含这些方法的类的同一实例上调用同步方法,则它们将阻塞。 If each thread instantiates a new object of the class containing the methods, they will not block since there will be two locks on two different instances of the class. 如果每个线程实例化包含方法的类的新对象,则它们不会阻塞,因为在该类的两个不同实例上将存在两个锁。

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

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