synchronize同步代码块做了啥?
1. 数据同步:同步代码块在获取锁后,首先从主内存中同步最新的数据到线程本地的工作内存中,在释放锁之前,将本地工作内存中的最新数据同步写入主内存中。
2. 原子操作
// 锁当前实例
public synchronized void func() {
}
// 锁class
public static synchronized void func() {
}
// 锁局部代码
public void func() {
Object o = new Object();
synchronized (o) {
}
}
有没有其他方式直接读写主内存?
有,volatile变量,适用于多线程环境中公共资源的共享,性能比同步代码块更高,效率更快,代价更低
1. 对volatile变量的读取数据,是直接在主内存中获取的。
2. 对volatile变量的写入,是直接写入到主内存中的。
3. 线程的本地工作内存是不保存副本的。
4. 对于数组是不能保证volatile的效果的。
5. volatile是可以保证long和double变量的原子操作的。
public class MyThread extends Thread{
private volatile boolean flag = true;
public boolean isFlag() {
return flag;
}
public void setFlag(boolean flag) {
this.flag = flag;
}
@Override
public void run() {
while (flag) {
System.out.println("I am counter");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("exit");
}
}
MyThread th = new MyThread();
th.start();
try {
Thread.sleep(3000);
}catch (InterruptedException e) {
}
th.setFlag(false);
如果flag不是volatile类型的,那么很有可能在调用setFlag后,线程无法中断。因为线程会在主内存中同步一份保存到本地的工作内存。
当使用volatile时,不再在本地工作内存中保存副本,而是直接读写主内存,因此,可以迅速地退出线程。