为什么说 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);

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

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

ReentrantLock nonFairLock = new ReentrantLock();

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

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

你可能感兴趣的:(Java,java)