java - 如果线程本身不请求锁,它可以更改 java 锁定的对象数据吗?

标签 java multithreading

Oracle 教程 Intrinsic Locks and Synchronization说:

Intrinsic[Monitor] locks play a role in both aspects of synchronization: enforcing exclusive access to an object's state

如果一个线程正在执行“同步”方法,我假设一个对象中的任何值都不能同时被两个线程操作。

因此,当以下代码具有以下输出时,我感到很惊讶(尽管出于我想要做的事情而松了一口气)。我不完全确定会发生什么,但是我认为可能会出现错误或某个点。

据我所知,如果另一个线程正在请求该对象的监视器状态,“同步”仅用于限制对该对象的访问——但如果另一个线程正在更改一次性值,则不会。这是正确的吗?

public class HelloWorld implements Runnable{
    Thread t1;
    Thread t2;
    int val1 = 0;
    int val2 = 0;

    public static void main(String[] args) {
        HelloWorld h1 = new HelloWorld();
        h1.t1 = new Thread(h1);
        h1.t2 = new Thread(h1);
        h1.t1.start();
        h1.t2.start();
    }

    @Override
    public void run() {
        System.out.println("STARTED");
        System.gc();
        Thread currentThread = Thread.currentThread();

        if (currentThread == this.t1) { 
            this.locker(); //This is a synchronized method, incrementing val1
        }
        if (currentThread == this.t2) {
            this.adder();  //This is a non-synchronized method, incrementing val2
        }
    }

    private synchronized void locker() {
        for(int i = 0; i < 3; i++){
            val1++;
            System.out.println("LOCKER: " + this.val1);
        }
    }

    private void adder() {
        while(this.val2 < 3) {
            this.val2++;
            System.out.println("ADDER: " + this.val2);
        }
        synchronized(this) {  
        //Synchronize for final output
            System.out.println("FINAL");
            System.out.println(val1);
            System.out.println(val2);     
        }
    }

}

STARTED
STARTED
ADDER: 1
LOCKER: 1
LOCKER: 2
ADDER: 2
LOCKER: 3
ADDER: 3
FINAL
3
3

最佳答案

“强制独占访问对象状态”的措辞可能会产生误导。同步代码可用于实现对对象状态的独占访问,但 (a) 它不强制执行此操作,并且 (b) protected 状态不一定是被锁定对象的状态。这在该教程后面的示例中进行了演示,其中两个对象 lock1lock2 用于保护字段 c1c2 不是自己状态的一部分。

synchronized 强制执行的是对 code 的独占访问 - 同一监视器上 synchronized block 中的任何代码只能由拥有该监视器的线程。这可用于确保对状态的独占访问 - 但前提是您正确编写代码(即,您将对该状态的所有访问都放在 synchronized block 中)。

没有什么能阻止您编写从不 protected 代码访问字段的程序,在这种情况下,不会强制执行独占访问。

关于java - 如果线程本身不请求锁,它可以更改 java 锁定的对象数据吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36106165/

相关文章:

Python多线程打印语句延迟到所有线程完成执行

python - 如何对 python 线程进行编程,以便用户可以使用 LINUX 中可用的监视工具来区分它们

java - 继承类中的静态成员变量

java - 在 mySQL 上运行多个并发语句

java - 为什么这个线程示例不起作用?都是 wait() 的

Java Grade类,字母等级转数字

android - InstrumentationTestCase2 中 AlertDialog 上的 peformClick() 不起作用

java - C++(可能还有 Java)如何为同步锁定对象?

java - 接口(interface) java.util.Map 是否覆盖 Object 类中的 hashCode() 和 equals()

java - 使用无限循环检查变量变化