In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-03-25 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/02 Report--
This article mainly introduces "how JUC simulates and semaphores". In daily operation, I believe many people have doubts about how JUC simulates and semaphores. The editor consulted all kinds of materials and sorted out simple and operation methods. I hope it will be helpful to answer the doubts of "how JUC simulates and semaphores". Next, please follow the editor to study!
1. An example of error
Here, first of all, explain that in order to meet the thread's unsuccessful application for semaphores, the process is blocked and inserted into the corresponding queue, so ReentrantLock+Condition is used to implement the Swait method. Don't say much nonsense, just go to the code:
/ / data definition static Lock lock = new ReentrantLock (); static Condition condition1 = lock.newCondition (); static Condition condition2 = lock.newCondition (); public static void Swait (String id, Semaphore S1, Semaphore S2) throws InterruptedException {lock.tryLock (1, TimeUnit.SECONDS); log.info ("status of current two semaphores: [{}, {}]", s1.availablePermits (), s2.availablePermits ()) / / availablePermits can get the remaining value if (s1.availablePermits ()) in the semaphore
< 1 || s2.availablePermits() < 1){ if (s1.availablePermits() < 1) { log.info("线程【{}】被挂起到信号量【{}】中", id, s1); //阻塞,并插入到condition1的阻塞队列中 condition1.await(); } else { log.info("线程【{}】被挂起到信号量【{}】中", id, s2); //阻塞,并插入到condition2的阻塞队列中 condition2.await(); } log.info("被挂起的线程【{}】被唤醒执行。", id); } else { log.info("为线程【{}】分配资源!", id); s1.acquire(); s2.acquire(); } lock.unlock(); } public static void Ssignal(Semaphore s1, Semaphore s2) throws InterruptedException { log.info("线程【{}】执行了释放资源", id); lock.tryLock(1, TimeUnit.SECONDS); s1.release(); s2.release(); //唤醒等待队列中的线程 condition.signal(); lock.unlock(); } 大家仔细看上面的代码,这个也是我刚开始写的代码,第一眼看似乎是没什么问题,但是里面隐藏着一个坑,在Swait方法中,调用condition1.await(),此时线程被阻塞在这一行中,但是当被别的线程(调用Ssignal)唤醒时,在被阻塞的下一行开始继续执行,但是在后续的代码里,是没有去申请信号量的,而是直接就Swait成功了,这样在执行Ssignal时就会导致信号量凭空的增加了,也就无法正确的表征系统中的资源数量了。 2.一个简单的示例 下面我们就对代码进行优化,大家可以回顾一下AND型信号量,当其因为资源不足时,需要将线程插入到第一个无法满足条件(即Si0){ count++; } } //如果资源都满足,则跳出循环,进行资源分配 if(count == list.length){ break; } log.info("线程【{}】被挂起-----", id); //将当前线程阻塞 condition1.await(); log.info("被挂起的线程【{}】被唤醒执行。", id); } log.info("为线程【{}】分配资源!", id); //分配资源 for (Semaphore semaphore:list){ semaphore.acquire(); } lock.unlock(); } public static void Ssignal(String id, Semaphore... list) throws InterruptedException { log.info("线程【{}】执行了释放资源", id); lock.tryLock(1, TimeUnit.SECONDS); //循环释放信号量 for (Semaphore semaphore:list){ semaphore.release(); } //唤醒等待队列中的线程 condition.signal(); lock.unlock(); } 为此,我们将方法中的信号量列表改为可变的参数列表,这样在传参的时候就可以方便的进行了,但是也会存才一些问题,比如无法约束"借出"与"归还"的信号量的数量是否一致。并且因为信号量的数量不定,所以无法为每个信号量新建一个条件变量(Condition),因此在上面的代码中所有的信号量公用一个条件变量,所有阻塞的线程都插入在其阻塞队列中。 4.一个完整的例子 这里我们使用一个经典的进程同步问题来演示我们使用Java模拟的AND型信号量,在这里,我们采用生产者–消费者问题来演示,完整的代码如下: //用来保证互斥的访问临界区(缓存区) static final Semaphore mutex = new Semaphore(1); //缓冲区,最大容量为50 static List buffer = new ArrayList(); //缓冲区中还可放入的消息数量 static final Semaphore empty = new Semaphore(50); //缓冲区中的消息数量 static final Semaphore full = new Semaphore(0); //可重入锁和条件变量 static Lock lock = new ReentrantLock(); static Condition condition = lock.newCondition(); //用与辅助的简单的生成消息 static Integer count = 0; //生产者 static class Producer extends Thread { Producer(String name) { super.setName(name); } @Override public void run() { do { try { Swait(this.getName(), mutex, empty); log.info("生产了一条消息:【{}】", count); buffer.add(count++); Thread.sleep(1000); Ssignal(this.getName(), mutex, full); } catch (InterruptedException e) { log.error("生产消息时产生异常!"); } } while (true); } } //消费者 static class Consumer extends Thread { Consumer(String name) { super.setName(name); } @Override public void run() { do { try { Swait(this.getName(), mutex, full); log.info("消费了一条消息:【{}】", buffer.remove(0)); Thread.sleep(1000); Ssignal(this.getName(), mutex, empty); } catch (InterruptedException e) { log.error("消费消息时产生异常!"); } } while (true); } } public static void Swait(String id, Semaphore... list) throws InterruptedException { lock.lock(); //如果资源不足,就挂起线程,并将线程插入到condition的队列中 while (true) { int count=0; for (Semaphore semaphore:list){ if(semaphore.availablePermits()>0) {count++;}} if (count = = list.length) {break;} log.info ("Thread [{}] is suspended", id); condition.await (); log.info ("suspended thread [{}] is woken up for execution." , id);} log.info ("allocate resources to threads [{}]!" , id); for (Semaphore semaphore:list) {semaphore.acquire ();} lock.unlock ();} public static void Ssignal (String id, Semaphore...) List) throws InterruptedException {log.info ("Thread [{}] performed resource release", id); lock.tryLock (1, TimeUnit.SECONDS); for (Semaphore semaphore:list) {semaphore.release ();} / / Wake up a thread in the waiting queue condition.signal (); lock.unlock ();} public static void main (String [] args) {Producer p1 = new Producer ("p1"); Consumer C1 = new Consumer ("C1") P1.start (); c1.start ();}
The above code can be executed directly, and if you don't need to use a parameter list, you can replace the above Swait method (remember to create the corresponding condition variable).
At this point, the study of "how to simulate and semaphores by JUC" is over. I hope to be able to solve your doubts. The collocation of theory and practice can better help you learn, go and try it! If you want to continue to learn more related knowledge, please continue to follow the website, the editor will continue to work hard to bring you more practical articles!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.