繁体   English   中英

实例的同步方法可以被同步语句锁定吗

[英]Can a synchronized method of an instance be locked by synchronized statement

我在并发的官方教程中遇到了一段代码:

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

我的问题是:

如果一个线程使用set方法,另一个线程可以使用其中一个同步方法,还是相反?

不,他们不能。 至少当您位于synchronized(this)块中时,才不会。 将非静态方法声明为已synchronized具有与将方法中的所有内容都放入synchronized(this) {}块相同的效果。

因此,当一个线程位于声明为synchronized的非静态方法内部时,其他任何线程都不能执行synchronized方法或synchronized(this) {}块。

对于在类ThisClass声明为static方法:对其处理方式与该方法的内容在synchronized(ThisClass.class) {}块内一样。


对于您的示例,如果您想知道为什么这不能正常工作:

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

getRGB()getName()确实this进行了锁定。 但是在这两个方法调用之间,再次释放了锁,以便另一个线程可以获取该锁,然后释放它,只有第一个线程才可以最终执行getName() 因此,另一个线程可以更改RGBName getter之间的颜色,因此返回的name和RGB将不适合同一颜色。

如果您这样做:

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

在这种情况下,对象的锁定不会在getRGB()getName()之间释放,因此此时没有线程可以获取它。

没有; synchronized方法将this同步。

而且,这是糟糕的代码; 整个类应该是不可变的,无需同步即可解决所有线程问题。

暂无
暂无

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

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