116 阅读1分钟
    1. 锁一定是可重入的;
    1. 程序执行过程中,一旦遇到异常,锁立即释放;

锁省升级过程

synchronize加锁之后,现在对象markword上记录这个线程的id(偏向锁); 如果有其他线程争用,第二个线程自旋等待第一个线程使用完(自旋锁),自旋锁一直占用系统内存; 自旋10次之后升级为重量级锁,进入等待队列。

Volatile

public class T {
    /*volatile*/ boolean running = true;

    private void m() {
        System.out.println("m start");
        while (running) {

        }
        System.out.println("m end!");
    }

    public static void main(String[] args) {
        T t = new T();
        new Thread(t::m).start();
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        t.running = false;
    }
}
  • 保证线程可见性
    • 线程有共享内存和工作内存,线程会先从共享内存中拷贝共享数据到工作内存,修改值之后写入共享内存,但是另一个内存什么时候去读,这个不好控制,线程之间不可见。
  • 禁止指令重排序
    • 一个对象创建过程:先申请内存空间赋默认值;然后将需要的值赋给变量;最后实例指向内存地址。保证创建过程中不被其他线程访问。 volatile 不能保证原子性