有关锁的内容

一、相关概念

1.什么是乐观锁、悲观锁

乐观锁是认为自己在使用数据的时候,没有其它线程会进行更改操作,因此不会添加锁,而是以来版本号或CAS自旋进行数据的校验。

悲观锁是认为自己在使用数据时,总有其它线程进行更改操作,因此一定会添加锁

 

2.什么是公平锁、非公平锁

公平锁是按照线程申请顺序来获取锁,Lock锁中,new ReentrantLock(true)代表公平锁

非公平锁并不会按照线程申请顺序来获取锁,有可能造成优先级反转和饥饿状态

非公平锁的效率更高,因为公平锁会频繁进行上下文切换,因此效率不如非公平锁

 

3.可重入锁

可重入锁的概念是锁里可以嵌套另一个锁,我们熟知的synchronized和Lock都是可重入锁

可重入锁内部有一个目标对象计数器,每有一个锁,就会+1,直到成为0,代表锁已被释放

 

4.中断锁机制

 

停止

一个线程不应该由其他线程来强制中断或停止,而是应该让线程自己自行停止,自己来决定自己的命运,所以。

Thread .stop, Thread.suspend,Thread.resume都已经被废弃了。

 

中断

中断是一种协商机制,并不是发出中断命令后线程立即中断,而是由线程自行停止。

每个线程对象中都有一个中断标识位,用于表示线程是否被中断;该标识位为true表示中斯,为false表示未中断。通过调用线程对象的interrupt方法将该线程的标识位设为true。可以在别的线程中调用,也可以在自己的线程中调用。

 

public void interrupt()

实例方法

interrupt()仅仅是设置线程中断状态为true

public static boolean interrupied()

静态方法

判断当前线程是否是中断状态,并重置中断状态为false

public boolean isInterrupted()

实例方法

判断当前线程是否被中断(检查标志位)

值得思考的是,我们来看下一段代码

        try{
            Thread.sleep(2000);
        }
        catch (InterruptedException e){
            Thread.currentThread().interrupt();//为什么要在一场出再调用一次
            e.printStackTrace();
        }

这是因为interrupt的性质

当线程正常运行时,那么会将线程的中断标记变为true。

当线程在阻塞状态中(例如sleep、wait、join),那么线程会立刻退出阻塞状态,并抛出InterruptedException异常。(并不会转变中断标记状态

 

那么如何中断运行中的线程呢?

  1. 通过volatile变量实现
  2. 通过AtomicBoolean
  3. 通过Thread自带的api实现

其中volatile和AtomicBoolean相当于一个flag,在线程外改变值,内部能接收到(if判断条件)

 

5.LockSupport类

LockSupport类是一个线程阻塞工具,它调用了Unsafe中的native代码,并提供了park()和unpark()方法

当调用park方法时,如果有凭证,则会直接消耗掉这个凭证然后正常退出。如果无凭证,就必须阻塞等待凭证可用。

unpark则相反,它会增加一个凭证。但凭证最多只能有1个。累加无效。

因此park和unpark必须出现并且park只能出现一次,因为无论多少个unpark只能存储一个凭证

它们并不像wait()和notify()方法一样必须一前一后,可以随意搭配。

 

posted @ 2023-03-15 22:05  冬日寻雾记  阅读(18)  评论(0)    收藏  举报