【java学习】java锁

1,概念

1)Java的线程是映射

Java的线程是映射到操作系统的原生线程之上的,如果要阻塞或唤醒一个线程,都需要操作系统来帮忙完成,这就需要从用户态转换到核心态中,因此状态装换需要耗费很多的处理器时间,对于代码简单的同步块(如被synchronized修饰的getter()和setter()方法),状态转换消耗的时间有可能比用户代码执行的时间还要长。

2)饥饿、活锁、死锁

2,自旋锁

1)概念

自旋锁是采用让当前线程不停地的在循环体内执行实现的,当循环的条件被其他线程改变时才能进入临界区。

2)场景

由于自旋锁只是将当前线程不停地执行循环体,不进行线程状态的改变,所以响应速度更快。
当线程数不停增加时,性能下降明显,因为每个线程都需要执行,占用CPU时间。如果线程竞争不激烈,并且保持锁的时间段少,适合使用自旋锁。

自旋等待避免了线程切换的开销,但要占用处理器时间的,因此,如果锁被占用的时间很短,使用自旋锁。因此,自旋等待的时间必须要有一定的限度,如果自旋超过了限定次数(默认是10次,可以使用-XX:PreBlockSpin来更改)没有成功获得锁,就应当使用传统的方式去挂起线程了。

自旋是在轻量级锁中使用的,在重量级锁中,线程不使用自旋。

3)实现

public class SpinLock {

  private AtomicReference<Thread> sign =new AtomicReference<>();

  public void lock(){
    Thread current = Thread.currentThread();
    while(!sign .compareAndSet(null, current)){ //使用CAS原子操作,设置sign为当前线程,并且预测原来的值为空  
    }
  }
  public void unlock (){
    Thread current = Thread.currentThread();
    sign .compareAndSet(current, null);//使用CAS原子操作,设置sign为null,并且预测值为当前线程。
  }
}

当有第二个线程调用lock操作时,由于sign值不为空,导致循环一直被执行,直至第一个线程调用unlock函数将sign设置为null,第二个线程才能进入临界区。

4)常见自旋锁

①TicketLock

Ticket锁主要解决的是访问顺序的问题,主要的问题是在多核cpu上。

②CLHlock

点击查看详情

③MCSlock

点击查看详情

3,乐观锁和悲观锁

1)概念

锁有两种:乐观锁与悲观锁。

①乐观锁

假定不会发生并发冲突,只在提交操作时检测是否违反数据完整性。(使用版本号或者时间戳来配合实现)。
在数据进行提交更新的时候,才会正式对数据的冲突与否进行检测,如果发现冲突了,则让返回用户错误的信息,让用户决定如何去做。。

乐观锁用到的机制就是CAS。

②悲观锁

有强烈的独占和排他特性。
不相信数据是安全的,故在数据处理过程中必须全部上锁,屏蔽一切可能违反数据完整性的操作。

2)CAS(Compare And Set或Compare And Swap)

3)举例

独占锁是一种悲观锁。

4)实现

悲观锁的实现,往往依靠数据库提供的锁机制(也只有数据库层提供的锁机制才能真正保证数据访问的排他性,否则,即使在本系统中实现了加锁机制,也无法保证外部系统不会修改数据)。

5,公平锁和非公平锁

1)概念

①公平锁

有优先级的锁。加锁前检查是否有排队等待的线程,优先排队等待的线程,先来先得。
多个线程在等待同一个锁时,必须按照申请锁的先后顺序来一次获得锁。

②非公平锁

加锁时不考虑排队等待问题,直接尝试获取锁(可抢占,阻塞的线程不会被唤醒),获取不到自动到队尾等待。

2)优缺点

①公平锁的好处是等待锁的线程不会饿死,但是整体效率低;

②非公平锁的好处是整体效率高,但是有些线程可能会饿死。

3)实现

new ReentrantLock(true)实现公平锁,new ReentrantLock(false)实现非公平锁。

7,独占锁

synchronized 是一种独占锁,synchronized 会导致其它所有未持有锁的线程阻塞,而等待持有锁的线程释放锁。

8,阻塞锁

1)概念

阻塞锁,让线程进入阻塞状态进行等待,当获得相应的信号(唤醒,时间) 时,才可以进入线程的准备就绪状态,准备就绪状态的所有线程,通过竞争,进入运行状态。

阻塞锁 被阻塞的线程,不会争夺锁。

2)场景(与自旋锁对比)

阻塞锁的优势在于,阻塞的线程不会占用cpu时间, 不会导致 CPU占用率过高,但进入时间以及恢复时间都要比自旋锁略慢。

在竞争激烈的情况下 阻塞锁的性能要明显高于 自旋锁。
理想的情况则是: 在线程竞争不激烈的情况下,使用自旋锁;竞争激烈的情况下使用,阻塞锁。

3)synchronized

4)ReentrantLock

5)Object.wait()\notify()

6)LockSupport.park()/unpart()(j.u.c经常使用)

9,可重入锁(递归锁)

1)概念

同一线程 外层函数获得锁之后 ,内层递归函数仍然有获取该锁的代码,但不受影响。(可多次进入改锁的域)

2)synchronized

3)重入锁(ReentrantLock)

reentrantlock要实现线程间的通信,必须创建条件锁。

借助于Condition对象,RetrantLock可以实现类似于Object的wait和notify/notifyAll功能。使用它具有更好的灵活性,在一个Lock对象里面可以创建多个Condition(对象监视器)实例,线程对象可以注册在指定的Condition对象中,从而可以有选择性的进行线程通知,实现多路通知功能,在调度线程上更加灵活。

10,读写锁

读写锁是一个资源能够被多个读线程访问,或者被一个写线程访问但不能同时存在读线程。
Java当中的读写锁通过ReentrantReadWriteLock实现。

1)readwritelock

当写操作时,其他线程无法读取或写入数据,而当读操作时,其它线程无法写入数据,但却可以读取数据 。
适用于读取远远大于写入的操作。

2)CopyOnWriteArrayList

11,互斥锁

所谓互斥锁就是指一次最多只能有一个线程持有的锁。在JDK中synchronized和JUC的Lock就是互斥锁。

12,偏向锁

1)概念

jvm控制,可以设置jvm启动参数。
锁会偏向于当前已经占有锁的线程。
无竞争不锁,有竞争挂起,转为轻量锁。

2)场景

竞争激烈的场合,偏向锁会增加系统负担。
没有竞争的场合,所以可以通过偏向来提高性能。

13,类锁和对象锁

1)概念

①类型

在方法上加上static synchronized的锁,或者synchronized(xxx.class)的锁。

②对象锁

锁住对象。

public class LockStrategy
{
    public Object object1 = new Object();
 
    public static synchronized void method1(){}//类锁
    public void method2(){
        synchronized(LockStrategy.class){}//类锁
    }
 
    public synchronized void method4(){}//对象锁
    public void method5()
    {
        synchronized(this){}//对象锁
    }
    public void method6()
    {
        synchronized(object1){}//对象锁
    }
}

14,线程锁

15,锁粗化

多锁变成一个,为了避免反复加锁解锁,避免频繁的互斥同步操作造成性能损耗,进行了锁范围的扩展。

16,轻量级锁和重量级锁

CAS 实现。
synchronized的偏向锁、轻量级锁以及重量级锁是通过Java对象头实现的。

17,锁消除

1)概念

虚拟机JIT在运行时,对一些代码上要求同步,但是被检测到不可能存在共享数据竞争的锁进行消除。

2)举例

偏向锁就是锁消除的一种。

18,锁膨胀

jvm实现,锁粗化。

19,信号量

使用阻塞锁 实现的一种策略。

20,共享锁(S锁)和排它锁(X锁)

操作系统中对锁的一种定义。java锁不存在X锁和排他锁

1)概念

①共享锁

如果事务T对数据A加上共享锁后,则其他事务只能对A再加共享锁,不能加排它锁。获准共享锁的事务只能读数据,不能修改数据。

②排它锁

如果事务T对数据A加上排它锁后,则其他事务不能再对A加任何类型的锁。获得排它锁的事务即能读数据又能修改数据。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值