zoukankan      html  css  js  c++  java
  • 多线程学习(八)

    原子性和易变性

    要理解黄色标注的内容那得 了解一下java中的内存模型:

    Java内存模型FAQ : http://ifeve.com/jmm-faq/
    同步和java内存模型: http://ifeve.com/syn-jmm/
    java内存模型指南: http://ifeve.com/jmm-cookbook/
    深入理解java内存模型: http://ifeve.com/java-memory-model-0/

    首先看完java内存模型我们了解到:java线程运行时分主存和线程的工作内存,线程的工作内存(相当于是缓存)会有主存的共享变量的副本,所有的修改和读取都是针对于线程的工作线程的。其实工作线程只是一个抽象的概念不一定存在

    看完这个你可能会有一点疑问?既然所有的线程读取和修改都是针对工作线程 那么他就应该是线程安全的啊 因为各个线程工作内存各自不影响啊!其实

    public class IntGeneratorActual extends IntGenerator {
    	private int val = 0;
    
    	@Override
    	public int next() {
    		System.out.println("Thread:" + Thread.currentThread().getName() + " read val:" + val);
    		val++;
    		System.out.println("Thread:" + Thread.currentThread().getName() + " yield before:" + val);
    		Thread.yield();
    		System.out.println("Thread:" + Thread.currentThread().getName() + " yield  after:" + val);
    		val++;
    		return val;
    	}
    
    	public int getVal() {
    		return val;
    	}
    }
    
    public class EvenChecker2 implements Runnable {
    	private IntGeneratorActual actual;
    
    	public EvenChecker2(IntGeneratorActual actual) {
    		super();
    		this.actual = actual;
    	}
    
    	@Override
    	public void run() {
    		// TODO Auto-generated method stub
    		while (true) {
    			int a = actual.getVal();
    			if (a % 2 != 0) {
    				System.out.println("get not steady val:" + a);
    				actual.cancel();
    				break;
    			}
    		}
    	}
    
    }
    
    public class JMMTest1 implements Runnable {
    	private IntGeneratorActual intGeneratorActual;
    
    	public JMMTest1(IntGeneratorActual intGeneratorActual) {
    		super();
    		this.intGeneratorActual = intGeneratorActual;
    	}
    
    	@Override
    	public void run() {
    		// TODO Auto-generated method stub
    		while (!intGeneratorActual.isCanceled()) {
    			int a = intGeneratorActual.next();
    			System.out.println("Thread:"+Thread.currentThread().getName()+" next:"+a);
    		}
    
    	}
    
    	public static void main(String[] args) {
    		ExecutorService executorService = Executors.newFixedThreadPool(5);
    		IntGeneratorActual actual = new IntGeneratorActual();
    		Runnable target = new JMMTest1(actual);
    		Runnable target2 = new EvenChecker2(actual);
    		for (int i = 0; i < 4; i++) {
    			executorService.execute(target);
    
    		}
    		executorService.execute(target2);
    		executorService.shutdown();
    	}
    }
    

    根据输出可以看出,你根本不知道 缓存什么时候会把 值写进 主存,也不知道什么时候 线程会读取主存中的值。你根本不知道线程的工作线程是否存在。(本人能力有限是在理解不了这一些).
    我总结如下:线程原子性的问题的时候就当没有线程的工作内存 所有的操作都像是直接针对主存
    线程可见性的问题的时候 是由于重排序导致的

  • 相关阅读:
    十进制转任意进制
    整型与字符串转换
    最长递增子序列(动态规划)
    睡眠理发师问题
    区间最值问题(RMQ)
    分解质因子
    数字统计
    After all, tomorrow is another day.
    【USB电平】电脑USB电平
    【有源滤波】滤波基础知识
  • 原文地址:https://www.cnblogs.com/joeCqupt/p/6821632.html
Copyright © 2011-2022 走看看