文章目录
synchronized 关键字初识
下面这三句话背下来面试很受用
1synchronize关键字提供了一种锁的机制,能够确保共享变量的互斥访问,从而防止数据不一致的问题出现。
2synchronize关键字包括monitor enter 和monitor exit两个jvm指令,它能够保证在任何时候任何线程执行到monitor enter成功之前都必须从主内存中获取数据,而不是从缓存中,在monitor exit运行成功之后,共享变量被更新后的值必须刷入主内存。
3synchronize的指令严格遵守java happens-before规则,一个monitor exit指令之前必定要有一个monitor enter。
synchronized 关键子的用法
synchronize 关键字可以对代码块或方法进行修饰,而不能够对于class以及变量进行修饰。
synchronized 需要注意的问题:
接下来的部分也背下来吧,蛮有用的
1与monitor 关联的对象不能为空
❎错误程序❌
private final Object mutex = null ;
public void syncMethod () {
synchronized(mutex){
//
}
}
mutex为null是个低级错误,每个对象和一个monitor关联,对象都为null,monitor更无从谈起了。
2synchronize 的作用域太大
❎错误程序❌
public static class Task implements Runnable {
@Override
public synchronized void run (){
//
}
}
synchronized 关键字应该尽可能的作用域共享资源(数据)的读写作用域。
3 不同的monitor 企图锁相同的方法
❎错误程序❌
public static class Task implements Runnable {
private final Object MUTEX = new Object() {
@Override
public void run (){
//...
synchronized(MUTEX){
//...
}
}
}
public static void main (String []args){
for(int i = 0 ;i<5;i++){
new Thread(Task::new).start();
}
}
}
4多个锁的交差导致死锁
多个锁交差容易造成死锁,程序没有任何错误输出,就是不工作。
...
private final Object MUTEX_READ = new Object ();
private final Object MUTEX_WRITE = new Object ();
public void read (){
synchronized (MUTEX_READ){
synchronized(MUTEX_WRITE){
//...
}
}
}
public void wtite (){
synchronized (MUTEX_WRITE){
synchronized(MUTEX_READ){
//...
}
}
}
This Monitor 和 ClassMonitor
this monitor
synchronized 关键字修饰了同一个实例对象的两个不同方法,那么与之对应的monitor是 this monitor ,两个monitor是一致的。
class monitor
synchronized 关键字修饰的同一个类的两个不同static 方法,那么与之对应的monitor是 class monitor ,两个monitor是一致的。
程序死锁的基本原因
1交叉锁可能导致出现死锁
线程A持有R1的锁等待R2的锁,线程B持有R2的锁等待R1的锁。
2内存不足
当并发请求系统可用内存时,如果此时系统内存不足,则可能会出现死锁的情况。 两个线程T1 and T2 ,执行某项任务,T1已经获取100M内存,T2获取200M内存,如果执行每个线程单元都需要300M内存,但是剩余可用内存刚好为200M,那么两个线程有可能都在等着彼此能释放内存资源。
3一问一答式的数据交换
服务的开启某个端口等待客户端访问,客户端发送请求立即等待接收服务端给的相应,由于某种原因服务端错过了客户端发送的信息,这时服务端与客户端都等待彼此发送信息过来,造成死锁。
4数据库
行级锁和表级锁。
5文件锁
某个进程一直占用某个文件,或者占用后没有及时关闭资源都会造成其他线程的死锁。
6死循环引起的死锁
代码处理不当进入死循环陷入假死状态。