Java里使用volatile进行线程同步的一个例子
Consider the following example:
package thread;
public class ThreadVerify {
public static boolean stop = false;
public static void main(String args[]) throws InterruptedException {
Thread testThread = new Thread(){
@Override
public void run(){
int i = 1;
while(!stop){
//System.out.println("in thread: " + Thread.currentThread() + " i: " + i);
i++;
}
System.out.println("Thread stop i="+ i);
}
};
testThread.start();
Thread.sleep(1000);
stop = true;
System.out.println("now, in main thread stop is: " + stop);
testThread.join();
}
}
The working thread is started to do increment on i and after one second, the flag is set as true in main thread. It is expected that we could see print out in working thread: “Thread stop i=”. Unfortunately it is NOT the case.
Through process explorer we can find the working thread is still running:
The only way we can terminate it is to click this button in Eclipse:
The reason is: every thread in Java has its own thread local stack in runtime. Every time a thread tries to access the content of a variable, it first locates the variable content in the main memory, then loads this content from main memory to its local stack. Once this load is done, this relationship between thread local stack and main memory is cut.
Later, when thread performs modifications on the variable, the change is directly done on thread local stack. And at a given time ( scheduled by JVM, developer has no control about this timeslot), the change will be refreshed from thread local stack to memory. Back to our example, already the main thread has changed the flag to true in one second later ( this is TOO late! ), unfortunately when the working thread reads the flag from its own local stack, the flag is still false ( it makes sense since when it is copied from main memory in main thread ), so the working threads could never end. See the following picture for detail.
Solution
Add keyword volatile to flag variable, to force the read access on it in working thread is done always from main memory, so that after the flag is changed to true in main thread, later the working thread can detect this latest change since it reads data from main memory now.
After this keyword is added we can get expected output:
要获取更多Jerry的原创文章,请关注公众号"汪子熙":
相关文章
- java中打印数组的方法_Java数组方法–如何在Java中打印数组
- Java并发——线程同步Volatile与Synchronized详解
- java session id 生成_Java通过sessionId获取Session「建议收藏」
- java 输入数组,最大的与第一个元素交换,最小的与最后一个元素交换,输出数组
- java基本数据类型 think in java_Think in Java(一):Java基础[通俗易懂]
- java生成license_使用truelicense实现用于JAVA工程license机制(包括license生成和验证)…
- Java实现水仙花代码「建议收藏」
- Java递归详解_java难不难学
- java softreference_Java引用总结–StrongReference、SoftReference、WeakReference、PhantomReference…[通俗易懂]
- Java-字符流逐行读取/写入文件
- Java项目冷更新数据双缓存方案 ( Redis + GuavaCache )
- Java线程池基本解读
- Java中注解学习系列教程-6 excel导出优化plush版
- JDK8的stream将list转Map对象时候报错:java.lang.IllegalStateException,解决
- c 线程安全的单例模式-c多线程并发处理方式_Java多线程面试题:线程锁+线程池+线程同步等
- Java 多线程详解(三)——线程的同步编程语言
- Java操作MySQL数据库:实现看似不可能的梦想(java连接mysql数据库)
- MySQL封装之Java实现(mysql封装java)
- Java 线程池理解详解编程语言
- 时间处理解决Java操作Redis过期时间问题(redisjava过期)
- Java中使用Redis包实现高效缓存(redis包java)
- Java如何启动MySQL?(java启动mysql)
- Java连接MySQL:实现数据库操作(java中连接mysql)
- Linux下Java命令:简介与基本用法(linux下java命令)
- Java与Oracle同步一种新的数据库模式(java同步oracle)