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

标签 java multithreading

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

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) block 中时不会。 将非静态方法声明为 synchronized 与将方法内的所有内容都放入 synchronized(this) {} block 中具有相同的效果。

因此,当一个线程在声明为 synchronized 的非静态方法中时,没有其他线程可以执行 synchronized 方法或 synchronized(this ) {} block 。

对于在类 ThisClass 中声明为 static 的方法:它们的处理方式与方法内容在 synchronized(ThisClass.类){} block 。


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

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 之间的颜色,因此返回的名称和 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() 之间的对象锁没有释放,因此此时没有线程可以获取它。

关于java - 实例的同步方法可以被同步语句锁定吗,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27910887/

相关文章:

c - 多线程和读取文件

java - runOnUiThread : Cant touch the View,异常

C 多线程值未打印

java - 使用值构造函数生成 JAXB 类时出现问题

java - 按 ctrl+C 退出 while 循环时执行代码

java - 当进度条达到最大值时,如何重置进度条并为其赋予新值?

C# 停止 TCP 文件传输

java - 错误 : "The method show() from the type Window is deprecated"

java - 如何解决 Android 上的 HttpGet 问题?

C++线程问题