欢迎访问宙启技术站
智能推送

Semaphore()的使用场景及示例代码

发布时间:2023-12-24 13:22:57

Semaphore是一种同步原语,用于控制多个线程对共享资源的访问。Semaphore维护了一个计数器,这个计数器表示当前可用的许可证数量。线程可以通过调用acquire()方法来请求一个许可证,如果计数器大于0,则线程会获得一个许可证,并将计数器减1;如果计数器等于0,则线程会被阻塞直到有其他线程释放了一个许可证。线程可以通过调用release()方法来释放一个许可证,这会将计数器加1。

Semaphore在以下场景下非常有用:

1. 限制资源的访问数量:Semaphore可以用来限制对某个资源的并发访问数量。例如,某个文件系统可能只允许同时有5个线程进行文件读取操作,其他线程需要等待。

2. 控制线程执行顺序:Semaphore也可以用来控制线程的执行顺序。例如,可以给每个线程分配一个许可证,线程只有在拿到许可证后才能执行,这样可以保证线程按照指定的顺序执行。

下面是一个使用Semaphore的示例代码,其中场景是限制对共享资源的并发访问数量:

import java.util.concurrent.Semaphore;

public class Resource {
    private Semaphore semaphore;
    
    public Resource(int concurrentAccess) {
        semaphore = new Semaphore(concurrentAccess);
    }
    
    public void doSomething() {
        try {
            semaphore.acquire(); // 请求许可证
            // 进行共享资源的访问
            System.out.println("Thread " + Thread.currentThread().getId() + " is accessing the resource");
            Thread.sleep(1000); // 模拟访问资源的耗时操作
            semaphore.release(); // 释放许可证
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

public class Main {
    public static void main(String[] args) {
        Resource resource = new Resource(3); // 允许同时有3个线程访问资源
        
        // 创建10个线程来访问资源
        for (int i = 0; i < 10; i++) {
            Thread thread = new Thread(() -> {
                resource.doSomething();
            });
            thread.start();
        }
    }
}

在上面的示例代码中,我们创建了一个Resource类来表示共享资源。在Resource类的doSomething()方法中,我们首先调用semaphore.acquire()方法来请求一个许可证,如果许可证可用,则线程会继续执行;否则线程会被阻塞。然后,线程进行共享资源的访问,这里只是打印一条日志来表示访问资源的操作。最后,线程调用semaphore.release()方法来释放许可证,其他被阻塞的线程将有机会获取到许可证并执行。

在Main类的main()方法中,我们创建了一个Resource对象,并指定可以同时有3个线程访问资源。然后,我们创建了10个线程来访问资源,每个线程都调用resource.doSomething()方法来进行资源的访问。由于我们限制了同时访问的线程数量为3,所以会有3个线程同时开始访问资源,其他线程需要等待。当一个线程完成访问后,它会释放许可证,此时其他线程将有机会获取许可证并开始访问资源。这样,通过Semaphore,我们可以限制对共享资源的并发访问数量,从而保护资源的安全性。