简体   繁体   中英

Can a synchronized method of an instance be locked by synchronized statement

I have run into a code piece in official tutorial of concurrency :

public SynchronizedRGB(int red,
                           int green,
                           int blue,
                           String name) {
        check(red, green, blue);
        this.red = red;
        this.green = green;
        this.blue = blue;
        this.name = name;
    }

    public void set(int red,
                    int green,
                    int blue,
                    String name) {
        check(red, green, blue);
        synchronized (this) {
            this.red = red;
            this.green = green;
            this.blue = blue;
            this.name = name;
        }
    }

    public synchronized int getRGB() {
        return ((red << 16) | (green << 8) | blue);
    }

    public synchronized String getName() {
        return name;
    }

    public synchronized void invert() {
        red = 255 - red;
        green = 255 - green;
        blue = 255 - blue;
        name = "Inverse of " + name;
    }
}

My question is :

If a thread uses set method, can another thread use one of the synchronized methods, or the other way around ?

No, they can't. At least not while you are inside the synchronized(this) block. Declaring a non-static method as synchronized has the same effect as putting everything inside the method into a synchronized(this) {} block.

Thus, while one thread is inside a non-static method declared as synchronized , no other thread may execute either a synchronized method or a synchronized(this) {} block.

For methods declared as static in the class ThisClass : They are handled the same way as if the contents of the method was inside a synchronized(ThisClass.class) {} block.


For your example, if you wonder why this does not work correctly:

SynchronizedRGB color = new SynchronizedRGB(0, 0, 0, "Pitch Black");
...
int myColorInt = color.getRGB();      //Statement 1
String myColorName = color.getName(); //Statement 2

getRGB() and getName() do lock on this . But between the two method calls the lock is released again so that another thread could acquire it, then release it, and only then the first thread could finally execute getName() . Thus another thread could change the color between the the RGB and the Name getter so the name and RGB returned would not fit to the same color.

If you do it like this:

SynchronizedRGB color = new SynchronizedRGB(0, 0, 0, "Pitch Black");
...
synchronized(color) {
    int myColorInt = color.getRGB();      //Statement 1
    String myColorName = color.getName(); //Statement 2
}

In this case the lock on the object is not released between getRGB() and getName() so that no thread could acquire it at this time.

No; synchronized methods will synchronize on this .

Also, this is poor code; the entire class should be immutable, solving all threading problems without synchronization.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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