并发编程 线程安全——synchronized
synchronized
概述:
synchronized是Java中的关键字 可以给方法和代码块加锁  (synchronized底层好像是通过C实现的)
可以保证方法或者代码块在运行时  同一时刻只有一个线程可以进入到临界区(临界区就是synchronized锁住的区域)
Java中每一个对象都可以作为锁  这是synchronized实现同步的基础 这里需要知道的是为什么Java的每个对象都可以作为锁
因为在Java中每个对象都有一个内置锁(监视器,也可以理解成锁标记),而synchronized就是使用对象的内置锁(监视器)来将代码块(方法)锁定的
- synchronized可以给方法和代码块加锁
- 加锁解锁的过程都是自动的
- synchronized关键字编译之后
 会在同步块的前后分别形成monitorenter和monitorexit这两个字节码指令
 这两个字节码指令都需要一个reference类型的参数来指明要锁定和解锁的对象
示例:
// 直接加在方法上 相当于当前方法为同步方法
// 加锁对象的话 实例类是this 静态类是class对象 (区别在于 一个锁住的是一个单独的实例 一个是整个静态类对象)  
public synchronized void Test1() {
    System.out.println("-----Test1------");
}
// 直接使用synchronized关键字 实现同步代码块 加锁对象程序员指定 一般指定为this
public void Test2(){
    synchronized (this){
        System.out.println("-----Test2------");
    }
}
优点:
- 加锁 解锁 过程都是底层帮我们处理了
- java的关键字,jvm原生支持
缺点:
- 效率低,试图获取锁时不能设定超时时间
 未得到锁的线程只能不停的尝试获得锁 而不能中断 高并发的情况下会导致性能下降
- 不够灵活 只能使用某个对象作为锁 且加锁和释放的时机单一
- 无法知道是否成功获得锁
- 锁的类型不可更改:可重入 不可中断 非公平
优化:
synchronized 属于重量级锁 1.6后Java对他进行了优化 出现了一个锁升级的概念(锁是不能降级的)
升级路线是:无锁 =》 偏向锁 =》 轻量级锁 =》 重量级锁
- 无锁:没有线程访问同步代码块时的状态
- 偏向锁:当有一个线程访问同步代码块时  无锁的就会升级为偏向锁 偏向当前线程(也就是第一个访问同步代码块的线程)
- 轻量级锁:当出现锁竞争的时候 偏向锁就会升级为轻量级锁
 轻量级锁也就是自旋锁 线程会自旋十次自旋是指竞争失败的线程循环获取锁(正常应该是竞争失败的线程阻塞)
 失败十次后 就会锁膨胀 (线程的自旋次数可以自己指定)
- 重量级锁:在轻量级锁自旋失败后 就会升级为重量级锁 也就是synchronized本来的级别

 
                
            
         浙公网安备 33010602011771号
浙公网安备 33010602011771号