Java锁-Synchronized

ReentrantLock的原理是改变抽象队列同步器中的state值来判断是否加锁
synchronized的原理是 修改对象头中的值

syn关键字

在JDK1.6之前是重量级锁

原因:
调用了操作系统的函数,
这里涉及到CPU 内核态与用户态的转换

JDK1.6之后做了优化
尽量在JVM层面解决锁的问题 但还是会调用操作系统函数

Synchronized修饰方法与代码块的异同

我们从编译过的文件可以看出直观异同

java代码:

public synchronized void test2() {
        System.out.println("test2");
    }

private String flag = "flag";    
public  void test4() {
        synchronized (flag) {
            System.out.println("test4");
        }
    }

编译后文件:

在这里插入图片描述

在这里插入图片描述
结论:
同步方法,JVM使用ACC_SYNCHRONIZED标识来实现。即JVM通过在方法访问标识符(flags)中加入ACC_SYNCHRONIZED来实现同步功能。
同步代码块,JVM使用monitorenter和monitorexit两个指令实现同步。即JVM为代码块的前后真正生成了两个字节码指令来实现同步功能的

Synchronized修饰静态方法和非静态方法区别

修饰静态方法时,是对类对象(.class)进行加锁
修饰非静态方法时,是对当前实例(this)进行加锁

Synchronized和lock的区别?

1、Synchronized是JVM层面,monitorenter和monitorexit,底层是通过monitor对象来完成加锁
wait,notify也依赖于monitor对象
lock是api层面
2、synchronized不需要手动释放锁,lock需要手动释放
3、等待是否可中断
synchronized不可中断 除非执行完成或发生异常
lock 可以中断,trylock加锁释放时间或者调用interrupt()方法
4、synchronized -非公平锁
lock 两者均可
5、condition概念
synchronized没有
lock 用来实现分组唤醒需要唤醒的线程们,可以精确唤醒,synchronized只能随机或者全部notifyAll

扫描二维码关注公众号,回复: 9542782 查看本文章

死锁

参考链接:https://www.cnblogs.com/bopo/p/9228834.html

发生死锁4个必要条件

互斥条件:一个资源每次只能被一个进程使用,即在一段时间内某 资源仅为一个进程所占有。此时若有其他进程请求该资源,则请求进程只能等待。

请求与保持条件:进程已经保持了至少一个资源,但又提出了新的资源请求,而该资源 已被其他进程占有,此时请求进程被阻塞,但对自己已获得的资源保持不放。

不可剥夺条件:进程所获得的资源在未使用完毕之前,不能被其他进程强行夺走,即只能 由获得该资源的进程自己来释放(只能是主动释放)。

循环等待条件: 若干进程间形成首尾相接循环等待资源的关系

如何避免死锁

让所有的线程按照同样的顺序获得一组锁。这种方法消除了 X 和 Y 的拥有者分别等待对方的资源的问题。

将多个锁组成一组并放到同一个锁下。前面Java线程死锁的例子中,可以创建一个银器对象的锁。于是在获得刀或叉之前都必须获得这个银器的锁。

将那些不会阻塞的可获得资源用变量标志出来。当某个线程获得银器对象的锁时,就可以通过检查变量来判断是否整个银器集合中的对象锁都可获得。如果是,它就可以获得相关的锁,否则,就要释放掉银器这个锁并稍后再尝试。

Synchronized如何保证不死锁

monitorenter之后有两处退出 monitorexit,其中一个是正常退出时调用 monitorexit,另一个是异常发生时 调用。

发布了328 篇原创文章 · 获赞 23 · 访问量 7万+

猜你喜欢

转载自blog.csdn.net/lbh199466/article/details/104313307