JAVA多线程并发工具之Threadlocal和volatitle

众所周知,要进行多线程开发必须要先熟悉JAVA并发工具包,工欲善其事必先利其器,下面讨论一下ThreadLocal和volatile的可见性问题!

java.lang.ThreadLocal:
Each thread holds an implicit reference to its copy of a thread-local variable as long as the thread is alive;
根据JDK中的解释,ThreadLocal为每个线程维护一份本地变量的副本,只要这个线程是alive,这份副本就一直存在;
volatile是JAVA中的关键字,volatile修饰的变量都会被同步到主存中,根据内存模型理解,同步到主存中也就意味这对其他的线程是可见的;
接下来抛出问题:
  如果一个对象Obj是被ThreadLocal维护的,Obj中有一个volatile修饰的成员变量variable,那么variable对于其他线程是可见的吗?

接下来上代码:

对象Obj

/**
 * @author wuhuagang
 * @date 2019/1/3
 * @desc
 */
public class Dto {
    private volatile ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();

    public ByteArrayOutputStream getByteArrayOutputStream() {
        return byteArrayOutputStream;
    }

    public void setByteArrayOutputStream(ByteArrayOutputStream byteArrayOutputStream) {
        this.byteArrayOutputStream = byteArrayOutputStream;
    }
}

主程维护ThreadLocal

/**
 * @author wuhuagang
 * @date 2019/1/3
 * @desc
 */
public class MainProgram {
    public static ThreadLocal threadLocal = new ThreadLocal<>();
    public static void main(String[] args) throws Exception {
        Dto dto = new Dto();
        threadLocal.set(dto);
        ThreadMain threadMain = new ThreadMain();
        threadMain.start();
        for(int i = 0;i<100;i++){
            dto.getByteArrayOutputStream().write("中国人民很行:".concat(Integer.valueOf(i).toString()).getBytes());
        }
    }
}
起一个线程去试试成员变量的可见性
/**
 * @author wuhuagang
 * @date 2019/1/3
 * @desc
 */
public class ThreadMain extends Thread{
    @Override
    public void run() {
        Dto dto = MainProgram.threadLocal.get();
        while (dto!=null){
            System.out.println("content:"+dto.getByteArrayOutputStream().toString());
        }
    }
}

结果:

content:中国人民很行:0中国人民很行:1中国人民很行:2中国人民很行:3中国人民很行:4中国人民很行:5  。。。

结果说明,volatile修饰的变量,即使变量存储在ThreadLocal的本地副本中,依然会被volatile同步到主存中,对其他线程可见,所以小伙伴们记住,这样的代码,即使是threadlocal结构的也会是产生安全问题的!

你可能感兴趣的:(JAVA多线程并发工具之Threadlocal和volatitle)