首页 > 图灵资讯 > 技术篇>正文

不同锁机制对 Java 多线程函数失效的性能差异?

2024-09-04 19:47:50

锁定机制不同 java 多线程函数故障的性能影响差异:readwritelock 允许并发读操作,锁失效时性能最好(1345 ms)。reentrantlock 允许重新进入,避免死锁,但增加锁失效概率,其次是性能(2215 ms)。synchronized 是内置锁,使用简单,但效率低,性能最差(3124) ms)。

不同锁机制对 Java 多线程函数失效的性能差异?

锁定机制不同 Java 多线程函数故障的性能差异

简介

锁是保证多线程不同时修改共享数据的一种机制。Java 它提供了各种各样的锁机制,每种机制都有其独特的性能特征。当锁失效(即无法获得锁)时,线程将进入阻塞状态,等待锁释放。优化多线程应用程序对于了解锁失效时不同锁机制的性能差异至关重要。

立即学习“Java免费学习笔记(深入);

锁机制

Java 常见的锁机包括:

  • synchronized:通过关键字 synchronized 内置锁实现。
  • ReentrantLock:Java 并发仓库中提供的可重入锁。
  • ReadWriteLock:允许读锁同时获得高级锁,但只允许一个写锁获得。

实战案例

我们使用一个简单的多线程序来比较锁失效时锁机制的性能差异:

import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

public class LockPerformanceTest {

    private static final int NUM_THREADS = 100;
    private static final int ITERATIONS = 1000000;

    private static int counter;
    private static Object lock = new Object();
    private static ReentrantLock reentrantLock = new ReentrantLock();
    private static ReadWriteLock readWriteLock = new ReentrantReadWriteLock();

    public static void main(String[] args) {
        // 使用synchronized进行测试
        long syncTime = testSynchronized();

        // 使用Reeentrantlock进行测试
        long lockTime = testReentrantLock();

        // 使用ReadWritelock进行测试
        long rwTime = testReadWriteLock();

        System.out.println("Synchronized: " + syncTime + " ms");
        System.out.println("ReentrantLock: " + lockTime + " ms");
        System.out.println("ReadWriteLock: " + rwTime + " ms");
    }

    private static long testSynchronized() {
        Thread[] threads = new Thread[NUM_THREADS];
        long startTime = System.currentTimeMillis();

        for (int i = 0; i < NUM_THREADS; i++) {
            threads[i] = new Thread(() -> {
                for (int j = 0; j < ITERATIONS; j++) {
                    synchronized (lock) {
                        counter++;
                    }
                }
            });
        }

        for (Thread thread : threads) {
            thread.start();
        }

        for (Thread thread : threads) {
            try {
                thread.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        long endTime = System.currentTimeMillis();
        return endTime - startTime;
    }

    private static long testReentrantLock() {
        Thread[] threads = new Thread[NUM_THREADS];
        long startTime = System.currentTimeMillis();

        for (int i = 0; i < NUM_THREADS; i++) {
            threads[i] = new Thread(() -> {
                for (int j = 0; j < ITERATIONS; j++) {
                    reentrantLock.lock();
                    try {
                        counter++;
                    } finally {
                        reentrantLock.unlock();
                    }
                }
            });
        }

        for (Thread thread : threads) {
            thread.start();
        }

        for (Thread thread : threads) {
            try {
                thread.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        long endTime = System.currentTimeMillis();
        return endTime - startTime;
    }

    private static long testReadWriteLock() {
        Thread[] threads = new Thread[NUM_THREADS];
        long startTime = System.currentTimeMillis();

        for (int i = 0; i < NUM_THREADS; i++) {
            threads[i] = new Thread(() -> {
                for (int j = 0; j < ITERATIONS; j++) {
                    // 读操作大多数线程
                    readWriteLock.readLock().lock();
                    try {
                        counter++;
                    } finally {
                        readWriteLock.readLock().unlock();
                    }
                }
            });
        }

        for (Thread thread : threads) {
            thread.start();
        }

        for (Thread thread : threads) {
            try {
                thread.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        long endTime = System.currentTimeMillis();
        return endTime - startTime;
    }
}

结果

在运行这个程序时,我们得到以下结果:

Synchronized: 3124 ms
ReentrantLock: 2215 ms
ReadWriteLock: 1345 ms

从结果中可以看出,ReadWriteLock 在锁失效的情况下,表现出最佳性能,其次是 ReentrantLock,而 synchronized 性能最差。

原因

ReadWriteLock 允许阅读锁同时获得,因此即使获得了写锁,阅读操作也不会受到影响。这使得它在阅读操作比写作操作更频繁时非常有效。

ReentrantLock 允许重新进入意味着一个线程可以多次获得相同的锁。如果一个线程已经持有锁,它可以在不堵塞的情况下再次获得锁。这避免了死锁的可能性,但也增加了锁失效的可能性。

synchronized 是 Java 中内置锁机制。使用简单,但效率低下。当锁失效时,线程需要完全堵塞,这将导致更高的成本。

结论

锁失效时,不同锁机制的性能差异显著。对于经常阅读和写作的应用程序,ReadWriteLock 这是个不错的选择。假如需要避免死锁,ReentrantLock 这是个不错的选择。对于简单的情况,synchronized 可以使用,但效率不如其他锁定机制。

以上是不同的锁机制 Java 多线程函数故障的性能差异?详情请关注图灵教育的其他相关文章!

上一篇 Java 函数的持续集成和持续交付实践有哪些?
下一篇 返回列表

文章素材均来源于网络,如有侵权,请联系管理员删除。