标签 ‘ Visibility

JIT与可见性

原文地址 (被墙移到墙内)

 Overview

Many developers of multi-threaded code are familiar with the idea that different threads can have a different view of a value they are holding, this not the only reason a thread might not see a change if it is not made thread safe.  The JIT itself can play a part.

Why do different threads see different values?

When you have multiple threads, they will attempt to minimise how much they will interact e.g. by trying to access the same memory.  To do this they have a separate local copy e.g. in Level 1 cache.  This cache is usually eventually consistent.  I have seen short periods of between one micro-second and up to 10 milli-seconds where two threads see different values.  Eventually the thread is context switched, the cache cleared or updated.  There is no guarantee as to when this will happen but it is almost always much less than a second. 阅读全文

可见性问题实例

说到并发安全时,我们常提及可见性的问题,通俗点讲就是线程1看不到线程2写入变量v的值(更专业的解释以及是什么导致可见性问题,又该如何解决,见扩展阅读),但一直偏于理论,实际中有没有因可见性而导致问题的例子呢?回答是肯定的,接下来我们一起来看几个例子。

这个例子很简单,新建的线程里有一个普通变量stop,用来表示是否结束循环里的自增操作。主线程启动这个线程后,将该变量置为true,观察线程是否打印出finish loop那行,如果存在可见性问题,主线程修改stop值为true,线程v看stop的值应该还是false。

class VisibilityThread extends Thread {
	private boolean stop;

	public void run() {
		int i = 0;
		System.out.println("start loop.");
		while(!getStop()) {
			i++;
		}
		System.out.println("finish loop,i=" + i);
	}

	public void stopIt() {
		stop = true;
	}

	public boolean getStop(){
		return stop;
	}
}

public class VisibilityTest {
	public static void main(String[] args) throws Exception {
		VisibilityThread v = new VisibilityThread();
		v.start();

		Thread.sleep(1000);//停顿1秒等待新启线程执行
		System.out.println("即将置stop值为true");
		v.stopIt();
		Thread.sleep(1000);
		System.out.println("finish main");
		System.out.println("main中通过getStop获取的stop值:" + v.getStop());
	}
}

阅读全文

Java内存模型Cookbook(四)指南(Recipes)

原文:http://gee.cs.oswego.edu/dl/jmm/cookbook.html

作者:Doug Lea 翻译:丁一

  1. 前言
  2. 指令重排
  3. 内存屏障
  4. 多处理器
  5. 指南

单处理器(Uniprocessors)

如果能保证正在生成的代码只会运行在单个处理器上,那就可以跳过本节的其余部分。因为单处理器保持着明显的顺序一致性,除非对象内存以某种方式与可异步访问的IO内存共享,否则永远都不需要插入屏障指令。采用了特殊映射的java.nio buffers可能会出现这种情况,但也许只会影响内部的JVM支持代码,而不会影响Java代码。而且,可以想象,如果上下文切换时不要求充分的同步,那就需要使用一些特殊的屏障了。

阅读全文

同步和Java内存模型 (三)可见性

原文:http://gee.cs.oswego.edu/dl/cpj/jmm.html 第三章
作者:Doug Lea 译者:程晓明 校对:方腾飞

只有在下列情况时,一个线程对字段的修改才能确保对另一个线程可见:

一个写线程释放一个锁之后,另一个读线程随后获取了同一个锁。本质上,线程释放锁时会将强制刷新工作内存中的脏数据到主内存中,获取一个锁将强制线程装载(或重新装载)字段的值。锁提供对一个同步方法或块的互斥性执行,线程执行获取锁和释放锁时,所有对字段的访问的内存效果都是已定义的。

注意同步的双重含义:锁提供高级同步协议,同时在线程执行同步方法或块时,内存系统(有时通过内存屏障指令)保证值的一致性。这说明,与顺序程序设计相比较,并发程序设计与分布式程序设计更加类似。同步的第二个特性可以视为一种机制:一个线程在运行已同步方法时,它将发送和/或接收其他线程在同步方法中对变量所做的修改。从这一点来说,使用锁和发送消息仅仅是语法不同而已。

阅读全文

return top