Java中的LockSupport和信号量semaphore

Java中的LockSupport是一个用于线程同步的工具类,它可以用来阻塞和唤醒线程。LockSupport通过许可证的方式来控制线程的执行。每个线程都有一个许可证(permit),如果许可证可用,线程就可以继续执行,如果许可证不可用,线程就会被阻塞挂起。

具体来说,当调用LockSupport.park()方法时,如果当前线程已经拥有许可证,那么该方法会立即返回。否则,该线程就会被阻塞挂起,等待许可证的释放。而LockSupport.unpark(Thread t)方法可以用来释放线程的许可证,从而唤醒该线程继续执行。

LockSupport的实现基于操作系统的底层原语,使用了类似于信号量(semaphore)的机制,因此它比一些其他的线程同步工具(如synchronized)具有更低的开销和更高的可用性。

总的来说,LockSupport是一种灵活、高效的线程同步工具,它可以很好地支持各种线程同步场景,但需要注意使用时要遵循一些规范和最佳实践,避免出现线程死锁或其他问题。

在Java中,信号量(Semaphore)是一种用于多线程同步的机制。它可以限制同时访问某个资源的线程数量,从而保证多线程之间的协作和同步。

Semaphore内部维护一个计数器,用于记录可用的许可证数量。当一个线程需要访问某个受信号量保护的资源时,它必须先获取一个许可证,即通过调用acquire()方法来请求许可证。如果此时可用的许可证数量大于0,那么线程可以立即获取许可证并继续执行;否则,线程就会被阻塞挂起,等待其他线程释放许可证。

当一个线程访问完受信号量保护的资源后,它必须通过release()方法释放许可证,使得其他线程可以获取许可证并继续执行。当一个许可证被释放后,Semaphore内部的计数器会相应地增加,表示可用的许可证数量增加了。

Semaphore还提供了一些其他的操作,比如tryAcquire()方法可以尝试获取许可证而不被阻塞,release(int permits)方法可以一次性释放多个许可证等等。

总的来说,Semaphore是一种非常有用的多线程同步机制,可以用来限制并发访问某些资源的线程数量,从而保证线程安全和程序的正确性。但需要注意,使用Semaphore时要遵循一些规范和最佳实践,避免出现死锁或其他问题。

1. 限制线程数量的示例

import java.util.concurrent.Semaphore;

public class ThreadLimitExample {
    private static Semaphore semaphore = new Semaphore(2);

    public static void main(String[] args) throws InterruptedException {
        for (int i = 0; i < 5; i++) {
            new Thread(() -> {
                try {
                    semaphore.acquire();
                    System.out.println(Thread.currentThread().getName() + " acquired semaphore");
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    semaphore.release();
                    System.out.println(Thread.currentThread().getName() + " released semaphore");
                }
            }).start();
        }
    }
}

这个示例中,我们创建了一个Semaphore对象,并设置初始的许可证数量为2。然后创建了5个线程,每个线程执行的代码是先请求许可证(通过semaphore.acquire()方法),如果可用的许可证数量大于0,那么线程就可以获取许可证并继续执行;否则,线程就会被阻塞挂起。当线程执行完毕后,需要通过semaphore.release()方法释放许可证,使得其他线程可以获取许可证并继续执行。

由于初始的许可证数量为2,因此最多只有两个线程可以同时执行。如果有多于两个线程请求许可证,那么剩下的线程就会被阻塞挂起,直到有线程释放了许可证。

2. 控制任务执行顺序的示例

import java.util.concurrent.Semaphore;

public class TaskSequenceExample {
    private static Semaphore semaphoreA = new Semaphore(1);
    private static Semaphore semaphoreB = new Semaphore(0);
    private static Semaphore semaphoreC = new Semaphore(0);

    public static void main(String[] args) {
        new Thread(() -> {
            try {
                semaphoreA.acquire();
                System.out.println("Thread 1 running");
                Thread.sleep(1000);
                semaphoreB.release();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();

        new Thread(() -> {
            try {
                semaphoreB.acquire();
                System.out.println("Thread 2 running");
                Thread.sleep(1000);
                semaphoreC.release();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();

        new Thread(() -> {
            try {
                semaphoreC.acquire();
                System.out.println("Thread 3 running");
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();

        semaphoreA.release();
    }
}

这个示例中,我们创建了三个Semaphore对象,分别表示三个任务的执行顺序。初始时,semaphoreA的许可证数量为1,semaphoreB和semaphoreC的许可证数量为0。这样就保证了第一个任务可以先执行,而其他两个任务需要等待第一个任务执行完毕后才能继续执行。

在主线程中,我们启动了三个线程,分别对应三个任务。每个线程执行的代码都是先通过

猜你喜欢

转载自blog.csdn.net/Jinliang_890905/article/details/130189231