ThreadLocal
为每个使用变量的线程提供独立的变量副本,这样每个线程就可以独立改变自己的副本,不会影响其他的线程;
InheritableThreadLocal在原有基础上进行了扩展,包括其子线程在内的线程都可以实现数据的同步;
synchronized
synchronized修饰的代码块或是方法都可以看作是一个原子操作;
一个线程执行互斥代码的过程:
1.获得同步锁;
2.清空工作内存;
3.从主内存拷贝对象到工作内存;
4.执行代码;
5.更新主内存内容;
6.释放同步锁;
volatile
volatile修饰的成员变量在每次被线程访问时,都会强制从共享内存中重新读该成员变量。同时,当成员变量发生变化时,会强制线程将变化后的结果写入共享内存总中。
但是volatile只提供了线程可见性,并没有提供线程的互斥性,故不能保证线程安全性和原子性;
volatile相当于synchronized的弱实现,但是效率比前者高。
由于其上述特性,volatile多应用于以下场合:状态标志、一次性安全发布、独立观察。
sleep、wait、notify
sleep会暂停一个进程,但是不会释放锁,等sleep时间到了会继续进行。
wait也会暂停一个进程,但是会释放锁,等时间到了需要通过notify或是allnotify执行。
可以看下面的例子:
public static void main(String[] args) throws Exception {
final Object lock="";
Thread t1=new Thread(){
public void run(){
try {
log.info("t1 wait begin");//1
synchronized (lock) {
log.info("t1 get lock, wait begin");//2
lock.wait();
log.info("t1 wait end,release lock");//9
lock.notifyAll();
}
log.info("t1 wait end");//10
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
t1.start();
log.info("t1 start and sleep");//3
for(int i=0;i<10000001;i++){
if(i==10000000)
log.info("i end");//4
}
Thread.sleep(5000);
log.info("sleep(5000) end");//5
log.info("main lock begin");//6
synchronized (lock) {
log.info("main get lock");//7
lock.notify();
log.info("notify");//8
Thread.sleep(10000);
log.info("sleep 10000 end");//11
log.info("main wait begin ");//12
lock.wait();
log.info("main wait end");//13
}
log.info("main lock end");
}