-
#synchronized与volatile
synchronized用来实现资源利用的互斥性,被其标识的区间同一时间只允许一个线程运行。
volatile被用于设计可见性,指的是一个线程操作完一个资源后,另一个线程获取到的一定是最新的资源数据,而不是缓存
#synchronized
@每个对象内部都有一个内部锁定(监控锁定),被标识为synchronized的代码块会被监控,任何线程要执行该代码块都必须先取得指定对象的内部锁定。多线程下竞争同一个锁定时,未竞争到的线程将进入等待锁定状态(blocked状态)。
@synchronized的使用方法
1.用来标识方法
2.用来标识代码块
//标识在方法上
...
public void synchronized functionA(){
...
}
...
//标识一个代码块
...
public void functionB(){
...
synchronized(this){
...
}
...
}
...
@synchronized默认是获取当前代码块或者方法所在类或者类的实例的锁定。
@Collection与Map可以使用Collections的下列方法进行打包,以获取对应的据有线程安全的对象。
Collections.synchronizedCollection()
Collections.synchronizedList()
Collections.synchronizedSet()
Collections.synchronizedMap()
...
@synchronized提供的是可重入同步,也就是说线程取得某个对象的锁定后,若执行过程中又要获取该锁定,则可以直接执行。
@对于synchronized设计不当,有可能造成“死结”, 即多线程下,线程之间对资源彼此交叉取用有可能造成“死结”。
#volatile
@在变量上标识volatile,表示变量是异变的,不允许线程快取,也就是如果有线程变动了变量值,另一个线程一定可以看到变更。
#竞争对象资源下的等待与通知
下面三个方法都是Object定义的方法。
1.wait(),执行synchronized范围内的代码时,如果调用了锁定对象的wait()方法,线程会释放对象锁定,并进入对象的等待集合,并且状态变更为Blocked,这时其它线程可以继续竞争对象锁定。wait()还可以指定时间,时间到了之后线程会再次加入对锁定的竞争。如果不指定时间,线程会一直等待下去,直到被中断(调用interrupt()方法)或被通知继续参与竞争(调用对象的notify()、notifyAll())。
2.notify(),从对象的等待集合中随机通知一个线程加入排班(即将锁定交给了它)。
3.notifyAll(),通知等待集合中所有的线程重新参与锁定的竞争。
#特别注意事项
多线程下,线程可能在未经过notify()、notifyAll()、interrupt()或逾时等情况下私自苏醒,应用程序设计时应该考虑这种情况,wait()在条件式成立的循环中执行。