美文网首页
各种锁🔒

各种锁🔒

作者: 王守伟 | 来源:发表于2017-07-16 22:50 被阅读0次

    (1)互斥锁

    a.每个对象都对应于一个可称为“互斥锁”的标记,这个标记用来保证在任一时刻,只能有一个线程访问该对象。

    b.Java对象默认是可以被多个线程共用的,只是在需要时才启动“互斥锁”机制,成为专用对象。

    c.关键字synchronized用来与对象的互斥锁联系

    d.当某个对象用synchronized修饰时,表明该对象已启动“互斥锁”机制,在任一时刻只能由一个线程访问,即使该线程出现堵塞,该对象的被锁定状态也不会解除,其他线程任不能访问该对象。

    (2)悲观锁

    悲观锁(Pessimistic Lock), 顾名思义,就是很悲观,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会block直到它拿到锁。传统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁。

    (3)乐观锁

    乐观锁(Optimistic Lock), 顾名思义,就是很乐观,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号等机制。乐观锁适用于多读的应用类型,这样可以提高吞吐量,像数据库如果提供类似于write_condition机制的其实都是提供的乐观锁。

    类似于SVN版本控制

    两种锁各有优缺点,不可认为一种好于另一种,像乐观锁适用于写比较少的情况下,即冲突真的很少发生的时候,这样可以省去了锁的开销,加大了系统的整个吞吐量。但如果经常产生冲突,上层应用会不断的进行retry,这样反倒是降低了性能,所以这种情况下用悲观锁就比较合适。

    (4)死锁

    a.)原因:AB两个线程,A运行中用到B。AB共用S(共享资源),A先运行,运行后由于S锁定,只能一个线程访问,B等待S运行堵塞,A等待B运行堵塞。两个线程互相等待,都无法运行

    b.)为避免死锁,就应该让线程在进入阻塞状态时尽量释放其锁定的资源,以为其他的线程提供运行的机会,可用方法:

    1.wait():被锁定的对象可以调用wait()方法,这将导致当前线程被阻塞并释放该对象的互斥锁,即解除了wait()方法当前对象的锁定状态,其他的线程就有机会访问该对象。

    2. notify():唤醒调用wait()方法后被阻塞的线程。

    3. notifyAll():唤醒所有调用wait()方法被阻塞的线程

    一旦发生死锁,进程被卡死,cpu占有率也是0,它不会占用cpu,它会被调出去。相对来说还是比较好发现和分析的。

    使用多线程的时候,一种非常简单的避免死锁的方式就是:指定获取锁的顺序,并强制线程按照指定的顺序获取锁。因此,如果所有的线程都是以同样的顺序加锁和释放锁,就不会出现死锁了

    (5)活锁

    活锁,指事物1可以使用资源,但它让其他事物先使用资源;事物2可以使用资源,但它也让其他事物先使用资源,于是两者一直谦让,都无法使用资源。

    举个例子,就如同你在街上遇到个人,刚好他朝着你的反方向走,与你正面碰到,你们都想让彼此过去。你往左边移,他也往左边移,两人还是无法过去。这时你往右边移,他也往右边移,如此循环下去。

    活锁会比死锁更难发现,因为活锁是一个动态的过程。

    (6)饥饿

    饥饿是指某一个或者多个线程因为种种原因无法获得所需要的资源,导致一直无法执行。

    (7)无锁

    是无障碍的,保证有一个线程可以胜出

    (8)公平锁­

    这个锁能保证线程是先来的先得到锁。虽然公平锁不会产生饥饿现象,但是公平锁的性能会比非公平锁差很多。

    相关文章

      网友评论

          本文标题:各种锁🔒

          本文链接:https://www.haomeiwen.com/subject/mfbxkxtx.html