synchronized同步方法
该关键字可用来保障原子性、可见性和有序性
方法内的变量为线程安全
多个线程的情况下,各个线程的变量为其私有,互不影响
实例变量非线程安全问题与解决方案
在被调用方法前加synchronized关键字上锁
同步synchronized在字节码指令中的原理
方法中使用synchronized实现同步的原因是使用了flag标记ACC_SYNCHRONIZED,当调用方法时,会先检查其是否设置没如果设置了则执行线程先持有同步锁,再执行方法,最后在方法完成时释放锁。
如果使用synchronized代码块,则使用monitorenter和monitorexit指令进行同步处理。
多个对象多个锁
如果多个线程的业务对象不一样,则他们的锁是单独的,并不存在争夺关系
将synchronized方法与对象作为锁
synchronized是锁对象,并非锁方法,只有拿到锁的线程才能调用该对象中所有的synchronized方法
脏读
在setValue()和getValue()设置synchronized关键字解决。
synchronized锁重入
如果一个线程获得了一个对象的锁,在没有释放的情况下这个线程还可以再次获取该对象的锁
锁重入支持继承的环境
当存在父子类继承关系时,自雷是完全可以通过锁重入调用父类的同步方法
出现异常,锁自动释放
当一个线程执行的代码出现异常时,其所持有的锁会自动释放。
重写方法不使用synchronized
如果重写方法不使用synchronized则是非同步方法,使用的话则是同步方法
public static boolean holdsLock(Object obj)方法的使用
当currentThread在指定的对象上保持锁定时才返回true
synchronized同步语句块
synchronized代码块是将任意对象作为锁,可以将锁看做一个标识,哪个线程持有这个标识,就可以执行同步方法。
synchronized方法的弊端
会导致某些不必要的时间浪费
synchronized同步代码块的使用
两个并发线程访问同一个对象object中的synchronized(this)同步代码块时,只能同步运行。
用同步代码块解决同步方法的弊端
只将重要代码放入synchronized(this)同步代码块中
一半异步,一半同步
不在synchronized块中就是异步执行,在synchronized块中就是同步执行。
synchronized代码块间的同步性
同一个对象的synchronized对所有的线程使用的锁是同一个(对象监视器是同一个)
同步synchronized(this)代码块是锁定当前对象的
将任意对象作为锁
synchronized和synchronized(this)同步代码块会将本类中其他的同步方法和同步代码块调用呈同步效果,同一时间只有赢线程可以执行同步方法或同步代码块中的代码。
多个锁就是异步执行
方法被调用是随机的
不同步导致的逻辑错误及其解决方法
在关键部分添加synchronized(this)同步代码块解决
类Class的单例性
每一个*.java文件对应的Class类的实例都是一个,在内存中是单例的。
静态同步synchronized方法与synchronized(class)代码块
加在静态方法上的方式是将类对应Class类的对象作为锁,加在非静态方法上是将方法所在的类的对象作为锁,这两个不是同一把锁
同步syn static方法可以对类的所有对象实例起作用
同步synchronized(class)代码块的作用和synchronized static方法的作用一样
String常量池特性与同步相关的问题与解决方案
如果以String常量作为锁的话,可能会导致多个线程的锁是同一个。可以通过new String()或者new Object()创建不同的对象
同步synchronized方法无限等待问题与解决方案
可以用同步块解决问题
多线程死锁
只要两个线程互相等待对方释放锁,就可能导致死锁。
内置类与静态内置类
新建内部类
(要用到类的实例对象myClass)
InnerClass innerClass = myClass.new InnerClass();
新建静态内部类
InnerClass innerClass = new InnerClass();
内置类与同步
如果持有不同的锁,他们则是异步的
锁对象改变导致异步执行
锁对象不改变依然同步执行
volatile关键字
1.可见性
2.原子性
3.禁止代码重排序
可见性测试
volatile关键字可以强制从公共内存中读取变量的值
synchronized代码块具有增加可见性的作用,synchronized关键字可以使多个线程访问同一个资源具有同步性,而且具有使线程工作内存中的私有变量与公共内存中的变量同步的特性
原子性的测试
使用volatile解决在32位系统中long或double数据类型写操作为非原子的情况。
volatile不适合处理i++操作,其是非原子操作,非线程安全的。
使用Atomic原子类进行i++操作实现原子性,如AtomicInteger
可以用synchronized关键字解决方法之间调用不同步的问题
禁止代码重排序测试
使用volatile和synchronized关键字可以禁止代码重排序
volatile之前和之后的代码可以重排
volatile之前的代码不可以重排到volatile之后
volatile之后的代码不可以重排到volatile之前
synchronized之前的代码不可以重排到synchronized之后
synchronized之后的代码不可以重排到synchronized之前