【问题标题】:Why doesn't the semaphore stop thrading?为什么信号量不停止运行?
【发布时间】:2021-03-07 12:04:42
【问题描述】:

我使用信号量,当列表大小为零时,我想要线程等待其他线程但是为什么信号量不停止运行?信号量不是像通知和等待一样工作吗?

结果: 添加 消除 添加 线程“Thread-2”java.lang.IndexOutOfBoundsException 中的异常:索引:0,大小:0

 ArrayList<String> list = new ArrayList<>();
            Semaphore semaphore = new Semaphore(0);
    
            new Producer(list, semaphore).start();
            new Producer(list, semaphore).start();
            new Customeer(list, semaphore).start();
            new Customeer(list, semaphore).start();
    //////////
        static class Customeer extends Thread {
    
            private List<String> list;
            private Semaphore semaphore;
    
            public Customeer(List<String> list, Semaphore semaphore) {
                this.list = list;
                this.semaphore = semaphore;
            }
    
            @Override
            public void run() {
    
    
                synchronized (list) {
                    if (list.size() == 0) {
                        try {
                            semaphore.acquire();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                        list.remove(0);
                        System.out.println("remove");
                }
            }
        }
    
        static class Producer extends Thread {
    
            private Semaphore semaphore;
            private List<String> list;
    
            public Producer(List<String> list, Semaphore semaphore) {
                this.list = list;
                this.semaphore = semaphore;
            }
    
            @Override
            public void run() {
    
                synchronized (list) {
    
                    list.add("hello");
                    semaphore.release();
                    System.out.println("add");
    
                }
    
            }
        }
    
    }

【问题讨论】:

    标签: java multithreading semaphore


    【解决方案1】:

    您似乎对信号量和同步感到困惑。当您希望允许 n 个线程一次访问同一资源时,使用信号量。 [n 可以是 1] 如果您希望只允许 1 个线程访问资源,则使用同步时。

    使用信号量的解决方案

    // Java implementation of a producer and consumer 
    // that use semaphores to control synchronization. 
    
    import java.util.concurrent.Semaphore; 
    
    class Q { 
        // an item 
        int item; 
    
        // semCon initialized with 0 permits 
        // to ensure put() executes first 
        static Semaphore semCon = new Semaphore(0); 
    
        static Semaphore semProd = new Semaphore(1); 
    
        // to get an item from buffer 
        void get() 
        { 
            try { 
                // Before consumer can consume an item, 
                // it must acquire a permit from semCon 
                semCon.acquire(); 
            } 
            catch (InterruptedException e) { 
                System.out.println("InterruptedException caught"); 
            } 
    
            // consumer consuming an item 
            System.out.println("Consumer consumed item : " + item); 
    
            // After consumer consumes the item, 
            // it releases semProd to notify producer 
            semProd.release(); 
        } 
    
        // to put an item in buffer 
        void put(int item) 
        { 
            try { 
                // Before producer can produce an item, 
                // it must acquire a permit from semProd 
                semProd.acquire(); 
            } 
            catch (InterruptedException e) { 
                System.out.println("InterruptedException caught"); 
            } 
    
            // producer producing an item 
            this.item = item; 
    
            System.out.println("Producer produced item : " + item); 
    
            // After producer produces the item, 
            // it releases semCon to notify consumer 
            semCon.release(); 
        } 
    } 
    
    // Producer class 
    class Producer implements Runnable { 
        Q q; 
        Producer(Q q) 
        { 
            this.q = q; 
            new Thread(this, "Producer").start(); 
        } 
    
        public void run() 
        { 
            for (int i = 0; i < 5; i++) 
                // producer put items 
                q.put(i); 
        } 
    } 
    
    // Consumer class 
    class Consumer implements Runnable { 
        Q q; 
        Consumer(Q q) 
        { 
            this.q = q; 
            new Thread(this, "Consumer").start(); 
        } 
    
        public void run() 
        { 
            for (int i = 0; i < 5; i++) 
                // consumer get items 
                q.get(); 
        } 
    } 
    
    // Driver class 
    class PC { 
        public static void main(String args[]) 
        { 
            // creating buffer queue 
            Q q = new Q(); 
    
            // starting consumer thread 
            new Consumer(q); 
    
            // starting producer thread 
            new Producer(q); 
        } 
    } 
    

    使用同步的解决方案

    // Java program to implement solution of producer 
    // consumer problem. 
    
    import java.util.LinkedList; 
    
    public class Threadexample { 
        public static void main(String[] args) 
            throws InterruptedException 
        { 
            // Object of a class that has both produce() 
            // and consume() methods 
            final PC pc = new PC(); 
    
            // Create producer thread 
            Thread t1 = new Thread(new Runnable() { 
                @Override
                public void run() 
                { 
                    try { 
                        pc.produce(); 
                    } 
                    catch (InterruptedException e) { 
                        e.printStackTrace(); 
                    } 
                } 
            }); 
    
            // Create consumer thread 
            Thread t2 = new Thread(new Runnable() { 
                @Override
                public void run() 
                { 
                    try { 
                        pc.consume(); 
                    } 
                    catch (InterruptedException e) { 
                        e.printStackTrace(); 
                    } 
                } 
            }); 
    
            // Start both threads 
            t1.start(); 
            t2.start(); 
    
            // t1 finishes before t2 
            t1.join(); 
            t2.join(); 
        } 
    
        // This class has a list, producer (adds items to list 
        // and consumber (removes items). 
        public static class PC { 
    
            // Create a list shared by producer and consumer 
            // Size of list is 2. 
            LinkedList<Integer> list = new LinkedList<>(); 
            int capacity = 2; 
    
            // Function called by producer thread 
            public void produce() throws InterruptedException 
            { 
                int value = 0; 
                while (true) { 
                    synchronized (this) 
                    { 
                        // producer thread waits while list 
                        // is full 
                        while (list.size() == capacity) 
                            wait(); 
    
                        System.out.println("Producer produced-"
                                        + value); 
    
                        // to insert the jobs in the list 
                        list.add(value++); 
    
                        // notifies the consumer thread that 
                        // now it can start consuming 
                        notify(); 
    
                        // makes the working of program easier 
                        // to understand 
                        Thread.sleep(1000); 
                    } 
                } 
            } 
    
            // Function called by consumer thread 
            public void consume() throws InterruptedException 
            { 
                while (true) { 
                    synchronized (this) 
                    { 
                        // consumer thread waits while list 
                        // is empty 
                        while (list.size() == 0) 
                            wait(); 
    
                        // to retrive the ifrst job in the list 
                        int val = list.removeFirst(); 
    
                        System.out.println("Consumer consumed-"
                                        + val); 
    
                        // Wake up producer thread 
                        notify(); 
    
                        // and sleep 
                        Thread.sleep(1000); 
                    } 
                } 
            } 
        } 
    } 
    

    阅读资源以获得更清晰的信息

    信号量:https://www.geeksforgeeks.org/producer-consumer-solution-using-semaphores-java/

    同步:https://www.geeksforgeeks.org/producer-consumer-solution-using-threads-java/

    【讨论】:

      猜你喜欢
      • 2015-07-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-09-30
      • 1970-01-01
      • 2020-04-12
      • 1970-01-01
      相关资源
      最近更新 更多