考虑以下简单示例:
public class Example extends Thread {
private int internalNum;
public void getNum() {
if (internalNum > 1)
System.out.println(internalNum);
else
System.out.println(1000);
}
public synchronized modifyNum() {
internalNum += 1;
}
public void run() {
// Some code
}
}
假设代码执行分为两个线程。假设,发生以下事件序列:
第一个线程访问
getNum
方法并缓存当前为0的internalNum
。同时,第二个线程访问获取锁的
modifyNum
方法,将internalNum
更改为1,然后退出释放锁。现在,第一个线程继续执行并打印
internalNum
。问题是将在控制台上打印什么?
我的猜测是,这个假设的示例将导致在控制台上打印1000,因为只有在进入或离开同步块时才在特定线程上强制进行读写刷新。因此,第一个线程将很乐意使用其缓存的值,而不知道它已被更改。
我知道使
internalNum
易变将解决可能的问题,但是我只是想知道天气是否真的必要。 最佳答案
假设代码执行分为两个线程。
它不会退出。但是,资源(方法,字段)可以由两个线程以并行方式访问。
我想你把事情混了。您的类扩展了Thread
,但是您的问题是关于通过并发线程访问同一实例的资源。
这是适合您问题的代码。
线程之间的共享资源:
public class SharedResource{
private int internalNum;
public void getNum() {
if (internalNum > 1)
System.out.println(internalNum);
else
System.out.println(1000);
}
public synchronized modifyNum() {
internalNum += 1;
}
public void run() {
// Some code
}
}
线程和运行代码:
public class ThreadForExample extends Thread {
private SharedResource resource;
public ThreadForExample(SharedResource resource){
this.resource=resource;
}
public static void main(String[] args){
SharedResource resource = new SharedResource();
ThreadForExample t1 = new ThreadForExample(resource);
ThreadForExample t2 = new ThreadForExample(resource);
t1.start();
t2.start();
}
}
你的问题 :
假设,发生以下事件序列:
第一个线程访问getNum方法并缓存internalNum
目前为0。同时第二个线程访问
ModifyNum方法获取锁,将internalNum更改为1,然后
退出释放锁。现在,第一个线程继续执行
打印internalNum
在您的方案中,给人的印象是
modifyNum()
方法的执行会阻止其他线程访问非同步方法,但事实并非如此。getNum()
不同步。因此,线程不需要获取对象上的锁即可执行它。在这种情况下,输出仅取决于哪个线程执行了第一个线程的指令:internalNum += 1;
要么
System.out.println(internalNum);
关于java - Java同步和数据一致性,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/41533796/