• 为什么说 java中的Synchronized是非公平锁


    Synchronized(同步块或同步方法)在Java中默认是非公平锁。这意味着当多个线程尝试获取同一个锁时,Synchronized不会按照请求锁的顺序分配锁,而是允许任何等待线程随机获取锁。这种锁的分配方式被称为非公平锁,因为它不考虑线程请求锁的顺序,而只是允许抢占。

    当锁被释放后,任何一个线程都有机会竞争得到锁,这样做的目的是提高效率,但缺点是可能产生线程饥饿现象。

    线程饥饿(Thread Starvation)是多线程编程中的一种现象,它指的是一个或多个线程由于无法获得所需的资源(例如CPU时间、内存、锁等),而被无限期地阻塞的情况。
    线程饥饿可能导致受影响的线程无法继续执行,甚至可能永远无法获得所需的资源,从而无法完成任务。这种情况通常是由于不公平的资源分配或者资源竞争问题引起的。

    非公平锁的优点是它的性能较好,因为它减少了线程切换的开销。线程可以在竞争激烈的情况下更容易地争夺锁,因此能够更快地执行。

    然而,非公平锁的不公平性可能导致某些线程被长时间地阻塞,而其他线程不断抢占锁。这可能导致某些线程的等待时间变得不确定,不利于某些场景中对线程执行时间的可控性和公平性要求。

    如果需要更严格的公平性,可以使用ReentrantLock的构造函数来创建公平锁,这将确保锁的分配遵循先进先出(FIFO)的原则,即按照请求锁的顺序分配锁。但需要注意的是,公平锁的性能可能会受到一些影响,因为它需要更多的线程切换操作来维护公平性。

    ReentrantLock

    ReentrantLock 是 Java 中的一个可重入锁,它可以用来代替 synchronized 关键字实现线程同步。ReentrantLock 提供了公平锁(Fair Lock)和非公平锁(Non-Fair Lock)两种模式。

    ReentrantLock 中,你可以通过在创建锁时指定 true 来创建一个公平锁。例如:

    ReentrantLock fairLock = new ReentrantLock(true);
    
    • 1

    在这种情况下,锁的获取将按照线程请求的顺序分配,即按照先进先出(FIFO)的原则。如果当前线程无法获取到锁,它将进入等待队列,直到轮到它获取锁为止。

    相反,如果你创建一个非公平锁,可以这样:

    ReentrantLock nonFairLock = new ReentrantLock();
    
    • 1

    在非公平锁模式下,当线程尝试获取锁时,如果锁当前是可用的,它会立即被分配给线程。这种模式下,线程没有进入等待队列的保障,可能会出现后来的线程比先前的线程更容易获取到锁的情况,因此可能存在线程“插队”的现象。

    使用公平锁可以确保锁的分配是按照请求的顺序进行的,而不是随机的。但需要注意,公平锁的性能通常会比非公平锁差,因为它需要更多的线程切换操作来维护公平性。因此,在选择锁的模式时,需要根据具体的应用场景和性能需求来权衡。

  • 相关阅读:
    普通人如何不被 OpenAI 取代?
    macOS 13 Ventura后,打开软件显示“XXapp已损坏,无法打开”如何解决?
    Elasticsearch:崭新的打分机制 - Learning To Rank (LTR)
    博客系统(升级(Spring))(四)(完)基本功能(阅读,修改,添加,删除文章)(附带项目)
    LeetCode(力扣)77. 组合Python
    【PAT甲级】1061 Dating
    qBittorrent-Enhanced-Edition便携版
    @Resource和@Autowired的区别
    系列四、Nginx的常用命令和配置文件
    脚手架构建VUE项目
  • 原文地址:https://blog.csdn.net/u011095039/article/details/133990670