Java高并发之锁的使用以及原理浅析(7)

这里,num指定初始许可计数。因此,它指定了一次可以访问共享资源的线程数。如果是1,则任何时候只有一个线程可以访问该资源。默认情况下,所有等待的线程都以未定义的顺序被授予许可。通过设置how为true,可以确保等待线程按其请求访问的顺序被授予许可。信号量的主要逻辑方法如下

// 从此信号量获取一个许可,在提供一个许可前一直将线程阻塞,否则线程被中断。 void acquire() // 从此信号量获取给定数目的许可,在提供这些许可前一直将线程阻塞,或者线程已被中断。 void acquire(int permits) // 从此信号量中获取许可,在有可用的许可前将其阻塞。 void acquireUninterruptibly() // 从此信号量获取给定数目的许可,在提供这些许可前一直将线程阻塞。 void acquireUninterruptibly(int permits) // 返回此信号量中当前可用的许可数。 // 释放一个许可,将其返回给信号量。 void release() // 释放给定数目的许可,将其返回到信号量。 // 仅在调用时此信号量存在一个可用许可,才从信号量获取许可。 boolean tryAcquire() // 仅在调用时此信号量中有给定数目的许可时,才从此信号量中获取这些许可。 boolean tryAcquire(int permits) // 如果在给定的等待时间内此信号量有可用的所有许可,并且当前线程未被中断,则从此信号量获取给定数目的许可。 boolean tryAcquire(int permits, long timeout, TimeUnit unit) // 如果在给定的等待时间内,此信号量有可用的许可并且当前线程未被中断,则从此信号量获取一个许可。

实例如下:这里我们模拟10个人去银行存款,但是该银行只有两个办公柜台,有空位则上去存钱,没有空位则只能去排队等待。最后输出银行总额

public class SemaphoreThread { private int customer; public SemaphoreThread() { customer = 0; } /** * 银行存钱类 */ class Bank { private int account = 100; public int getAccount() { return account; } public void save(int money) { account += money; } } /** * 线程执行类,每次存10块钱 */ class NewThread implements Runnable { private Bank bank; private Semaphore semaphore; public NewThread(Bank bank, Semaphore semaphore) { this.bank = bank; this.semaphore = semaphore; } @Override public void run() { int tempCustomer = customer++; if (semaphore.availablePermits() > 0) { System.out.println("客户" + tempCustomer + "启动,进入银行,有位置立即去存钱"); } else { System.out.println("客户" + tempCustomer + "启动,进入银行,无位置,去排队等待等待"); } try { semaphore.acquire(); bank.save(10); System.out.println(tempCustomer + "银行余额为:" + bank.getAccount()); Thread.sleep(1000); System.out.println("客户" + tempCustomer + "存钱完毕,离开银行"); semaphore.release(); } catch (InterruptedException e) { e.printStackTrace(); } } } /** * 建立线程,调用内部类,开始存钱 */ public void useThread() { Bank bank = new Bank(); // 定义2个新号量 Semaphore semaphore = new Semaphore(2); // 建立一个缓存线程池 ExecutorService es = Executors.newCachedThreadPool(); // 建立10个线程 for (int i = 0; i < 10; i++) { // 执行一个线程 es.submit(new Thread(new NewThread(bank, semaphore))); } // 关闭线程池 es.shutdown(); // 从信号量中获取两个许可,并且在获得许可之前,一直将线程阻塞 semaphore.acquireUninterruptibly(2); System.out.println("到点了,工作人员要吃饭了"); // 释放两个许可,并将其返回给信号量 semaphore.release(2); } public static void main(String[] args) { SemaphoreThread test = new SemaphoreThread(); test.useThread(); } }

View Code

读写锁ReentrantReadWriteLock

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/0e6f83f129bd3fde91f845da9f5e6d21.html