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 状态不一定是被锁定对象的状态。这在该教程后面的示例中进行了演示,其中两个对象 lock1
和 lock2
用于保护字段 c1
和 c2
不是自己状态的一部分。
synchronized
强制执行的是对 code 的独占访问 - 同一监视器上 synchronized
block 中的任何代码只能由拥有该监视器的线程。这可用于确保对状态的独占访问 - 但前提是您正确编写代码(即,您将对该状态的所有访问都放在 synchronized
block 中)。
没有什么能阻止您编写从不 protected 代码访问字段的程序,在这种情况下,不会强制执行独占访问。
关于java - 如果线程本身不请求锁,它可以更改 java 锁定的对象数据吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36106165/