Java多线程(一)--synchronized

synchronized

  synchronized保证使用同一个对象锁的代码块在同一时间只能被一个线程执行。方法对象静态方法class类锁都属于对象锁(Class对象是唯一的、全局的)
方法this对象
对象:创建的对象
静态方法:方法所在类的Class对象
class类锁Class对象

用法

对象锁

  • 代码块
      如果只有一个obj对象,当线程1执行到synchronized代码块时,线程2想执行synchronized代码块的话要等obj的锁被释放,也就是线程1把synchronized代码块执行完成。因为这里使用的是同一个对象

    Object obj=new Object();
    
    synchronized(obj){
        ...
    }
    

    另一种写法是使用this,因为this指的是当前对象,所以和上面的意思一样

    synchronized(this){
        ...
    }
    
  • 方法
    直接加在普通方法上和synchronized(this)意思一样,直接使用当前对象加锁

    public synchronized void doSomething(){
      ...
    }
    

类锁

  • 代码块
      因为所有class都含有一个Class对]象,并且在程序运行时是唯一的,所以就相对于使用的是同一个对象进行加锁

    synchronized(Main.class){
        ...
    }
    
  • 方法(static)
      synchronized修饰普通方法加锁的是方法所在对象,而在静态方法里面使用加锁的是方法所在的类的class对象,所以效果等同于类锁的代码块形式

    public synchronized static void doSomethong(){
        ...
    }
    

性质

  • 不可中断
    只能等待另一个线程释放锁之后才能获取锁
  • 可重入性质
    同一线程的外层获取锁之后,内层也可以再次获得锁,而不需要等待释放锁。避免了外层获取而内层不能获取,然后外层又因为内层阻塞释放不了锁而形成的死锁
    锁的粒度是线程

原理

  • 可见性原理:解锁时把工作内存的共享变量值刷新到主内存,加锁时清空工作内存的共享变量值

  • 加锁和释放锁使用monitor来实现

  • 重入锁靠的加减monitor

    • 当获得锁之后,monitor+1,当内部代码再次获取锁时,monitor再+1
    • 内部代码执行完离开时,monitor-1,外层执行完成再次-1
    • monitor等于0时说明锁已经被释放了,不等于0则其它尝试获取锁的线程会阻塞
  • 加锁使用monitorenter,释放使用monitorexit
    可以通过反编译代码看到

    • 先使用javac编译下面的代码
    public void test(){
        synchronized(this){
            ...
        }
    }
    
    • 然后使用javap -verbose 类名获得汇编代码(这里截取部分反编译后的代码)
      可以看到3:处加锁使用的monitorenter以及5:处使用的monitorexit
    0: aload_0
    1: dup
    2: astore_1
    3: monitorenter
    4: aload_1
    5: monitorexit
    6: goto          14
    9: astore_2
    10: aload_1
    11: monitorexit
    12: aload_2
    13: athrow
    14: return
    

缺点

  • 效率低
    • 锁的释放情况少
    • 不可中断
    • 获取锁不能设置超时
  • 不够灵活
    • 加锁和释放时机单一
    • 每个锁只有单一的条件
  • 无法知道锁的获取状态

注意点

  • 锁对象不能为空,否则会报异常,因为加锁靠的是对象的monitor
  • 作用域不要太大,否则可能效率低
  • 避免死锁
  • 使用推荐:并发包 > synchronized > Lock
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值