volatile关键字
最轻量的同步机制: 可以保证可见,但是不能保证原子。
//演示Volatile的提供的可见性
public class VolatileCase {
private static boolean ready;
private static int number;
private static class PrintThread extends Thread{
@Override
public void run() {
System.out.println("PrintThread is running......");
while (!ready);
System.out.println("number = "+number);
}
}
public static void main(String[] args) throws InterruptedException {
new PrintThread().start();
Thread.sleep(1000);
number=51;
ready=true;
Thread.sleep(5000);
System.out.println("main is ended");
}
}
结果:
说明主程序中ready做的修改没有被线程看到。
现在把ready改为如下:
private volatile static boolean ready;
结果:
说明加了volatile之后,主线程的修改能被看见,但是它只能保证可见性,不能保证原子性,即不能保证某个数据在多个线程下同时写的时候的安全。
应用场景:一写多读。
ThreadLocal辨析
ThreadLocal : 每个线程都有变量的副本,实现线程的隔离。
Spring在实现事物的时候要借助ThreadLocal。
下面来看看如下例子:
public class UseThreadLocal {
private static ThreadLocal<Integer> threadLocal=new ThreadLocal<Integer>(){
@Override
protected Integer initialValue() {
return 1;
}
};
/*
运行三个线程
*/
public void StartThreadArray(){
Thread[] runs=new Thread[3];
for(int i=0;i<runs.length;i++){
runs[i]=new Thread(new TestThread(i));
}
for (int i=0;i<runs.length;i++){
runs[i].start();
}
}
/*
类说明:测试线程,线程的工作是将ThreadLocal变量的值变化,并写回,看看线程之间是否会相互联系
*/
public static class TestThread implements Runnable{
int id;
public TestThread(int id){
this.id=id;
}
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+".start");
Integer s=threadLocal.get();
s=s+id;
threadLocal.set(s);
System.out.println(Thread.currentThread().getName()
+":"+threadLocal.get());
}
}
public static void main(String[] args) {
UseThreadLocal test=new UseThreadLocal();
test.StartThreadArray();
}
}
结果如下:
说明能让每个线程有独立的副本。
如果定义多个ThreadLocal会放到map里面。
每个线程有个自己的ThreadLocalMap。
Entry(ThreadLocal<?> k, Object v){
super(k);
value=v;
}
引用:强引用、软引用、弱引用、虚引用
Object o=new Object(); //强引用
SoftRefence 要发生溢出 软引用
所有的弱引用都在ThreadLocal 所标志出来:extends WeakReference<ThreadLocal<?>> 。意味着只要发生垃圾回收,这个thread变量就一定会被回收。