简介:对多线程可见,保证同一时刻最多只有一个线程执行代码,达到线程并发安全,被修饰的代码保证了可见性、一定程度上的原子性和禁止指令重排序。关键是独占一个锁。关键字,java原生支持,最基本的互斥同步手段。
如果不使用并发手段的后果:比如两个线程同时执行a++,最后结果比预期的要少
原因:a++包含三个操作不具有原子性,读取a值,a+1,然后写入内存,共分三个步骤抢占式调度引起,底层原理是java内存模型机制引起。
用法:
对象锁:方法锁(默认对象为this当前实例对象)和同步代码块锁(自己指定锁对象包括this)
类锁:指Synchrinized修饰的静态方法或者代码块指定锁为Class对象,java类可以用很多对象,只有一个Class对象
锁不同相互没有影响--并行而非串行
类锁可以全局保护,不同的对象实例进来也可以同步执行如New Thrend(class.this1)和
New Thrend(class.this2),同时执行同步代码块,对象锁是并行的而类锁可以同步执行
多线程访问同步方法的七种情况
1:两个线程同时访问一个对象的同步方法
同一把锁存在阻塞
2:两个线程访问来两个对象的同步方法
锁住不同的实例,所以不会阻塞
3:两个线程访问的是静态方法
锁对象为Class对象,存在阻塞
4:如果同时访问同步方法和非同步方法
非同步方法不会受到影响
5:访问同一个对象的不同的普通同步方法
锁是一样的,发生阻塞
6:同时访问静态和非静态的同步方法
两个锁不一样,不受影响,串行
7:方法抛出异常,会释放锁
总结:
a:一把锁只能同时被一个线程获取,没有拿到锁的线程必须等待
b:每一个实例都对应有自己的一把锁,不同的实例之间相互不影响,但是Class对象锁,所有对象公用一把锁
c:无论正常执行完毕还是抛出异常都会释放锁
Synchrinized性质:
1.可重入(递归锁):同一线程外层函数获得锁之后,内层函数可以直接再获取该锁,避免死锁,提升封装性,粒度:线程而非调用
2. 独占
可重入性质:
1: 同一个方法可重入
2:可重入不要求是同一个方法
3:可重入不要求是同一个类
不可中断:一旦锁已经被别人获得,,如果我想再想获得,就只能等待或者阻塞,直到别的线程释放锁,否则会一直等待下去(与Lock比,可以设置超时时间)
原理
1:加锁和释放锁
现象
内置锁
等价代码----Lock
深入JVM字节码:
概况:java对象头存储synchrinized,基于monitor
反编译:monitorenter开始锁住代码块,monitorexit释放锁
Monitorenter:+1获取锁,重入再+1,其他线程阻塞
Monitorexit:计数器-1,为0就失去monitor的所有权,其他线程可以获取可以获取锁
2:可重入原理:每一个对象都有一把琐,jvm负责跟踪对象被加锁的次数
线程第一次给对象加锁的时候,计数器变为1,每当相同的线程此对象上再次获得锁,计数器会递增
每当任务离开的时候,计数递减,每当计数为0的时候,锁被完全释放
3:保证可见性原理:
Java内存模型:1:主内存数据复制副本到工作内存,2更新,3更新后把数据写入主内存中,一旦被synchrinized修饰,同时只有一个线程修改数据,所以修改对其他线程是可见的,保证线程安全性
缺陷:
效率低:所得释放情况少,只有当前线程执行结束和发生异常才释放锁,试图获得时不能设定超时时间,不能中断一个正在试图获得锁的线程---Lock对比
不够灵活(读写锁更加灵活):加锁和释锁的时机单一,每个锁仅有单一的条件(某个对象),可能是不够的
无法知道是否成功的获取了锁
---Lock接口对比
Lock lock =new reenetrylock
lock.lock()
lock.unLock()
lock.tryLock() ----返回boobean
lock.trylock(超时时间)----返回boobean
思考:
1:使用注意点:锁对象不能为空、作用域不宜过大(效率低)、避免死锁
2:如何选择sync和Lock?
建议:如果可以都不使用,使用并发包中的类,考虑开发效率,出错机率以及执行效率
3:多线程访问同步方法的各种具体情况
思考:
1:多个线程等待同一个synchronized锁的时候,JVM如何选择下一个获取锁的线程,涉及锁的调度机制
2:sync使得同时只有一个线程可以执行,性能差,如何提高性能,优化锁的范围尽可能小,
可以替代,比如读写锁
3:更加灵活的控制锁的获取和释放?
4:什么是锁的升级、降级?什么是JVM里的轻量级锁、偏斜锁、重量级锁?
总结:
一句话介绍synchronized:
Jvm会自动通过使用monitro来加锁和解锁,使锁住的代码块具有原子性操纵,保证只有一个线程可以执行指定的代码,从而保证线程安全,同时具有可重入和不可中断的性质
ps:写的不够好,如果有不足或者错误的地方欢迎留言指正