线程通信有两种方式:共享内存与消息传递。
共享内存即多个线程共享程序的公共变量,通过变量状态的读写来进行隐式共享;消息传递则是线程之间没有公共变量,而是通过消息传递来进行显示的通信。而在Java中,采用的是共享内存来进行线程间通信(多线程共享变量方式 )
Java中线程间通信由Java内存模型(JMM)来控制,JMM决定了共享变量的写入何时对另一个线程可见。JMM的抽象示意图如下:
可以看到,每个线程都是有一个共享变量的副本,每次访问都是先访问共享变量副本,如果没有做出同步操作,那么可能会导致一些内存一致性问题。下面做一个实验。
实验性质:验证性实验
实验目的:验证内存一致性问题真实存在。
实验步骤:1. 创建一个读线程,对共享变量进行读取操作,并打印读取的结果;2.创建一个写线程,对共享变量进行修改,并打印修改后的结果;3.观察打印结果
共享变量:
public class Model {
public int i;
}
读线程:
public class ReadThread extends Thread {
Model model;
public ReadThread(Model model) {
this.model = model;
}
@Override
public void run() {
while (true) {
System.out.println(this.getName() + ":"
+ System.currentTimeMillis() + ":" + model.i);
}
}
}
写线程:
public class WriteThread extends Thread {
Model model;
public WriteThread(Model model) {
this.model = model;
}
@Override
public void run() {
while (true) {
model.i++;
System.out.println(this.getName() + ":"
+ System.currentTimeMillis() + ":" + model.i);
}
}
}
主函数:
public class Main {
public static void main(String[] args) throws IOException {
File file = new File("E://log.txt");
if(!file.exists()){
file.createNewFile();
}
System.setOut(new PrintStream(file));
Model model = new Model();
model.i = 1;
ReadThread readThead = new ReadThread(model);
readThead.setName("readThread");
WriteThread writeThread = new WriteThread(model);
writeThread.setName("writeThread");
readThead.start();
writeThread.start();
}
}
测试结果(节选有问题片段):
readThread:1444028570784:2
writeThread:1444028570784:2
readThread:1444028570784:2
writeThread:1444028570784:3
writeThread:1444028570784:4
readThread:1444028570784:3
writeThread:1444028570784:5
readThread:1444028570784:5
writeThread:1444028570784:6
readThread:1444028570784:6
注意第七行位置,writeThread已经读到i的值变为4,而readThread读取到的值仍为3.
一起学习交流呀