zoukankan      html  css  js  c++  java
  • 经典线程同步问题

    生产者消费者问题

    读者作家问题

    哲学家吃饭问题

    生产者消费者问题

     
    分别用锁、信号量、同步监视器模拟的例子。
    package thread;
    
    import java.util.Random;
    import java.util.concurrent.Semaphore;
    import java.util.concurrent.locks.Condition;
    import java.util.concurrent.locks.Lock;
    import java.util.concurrent.locks.ReentrantLock;
    
    class Item {
        int id;
    
        public Item(int id) {
            this.id = id;
        }
    
        public String toString() {
            return "[item " + id + "]";
        }
    }
    
    abstract class Buffer {
        int capacity;
        Item[] items;
        int count;
        int in, out;
    
        public Buffer(int capacity) {
            this.capacity = capacity;
            items = new Item[capacity];
            count = 0;
            in = out = 0;
        }
    
        abstract void put(Item item);
    
        abstract Item get();
    
        public void printBuf() {
            System.out.print("current buf status: [ ");
            for (int i = 0; i < capacity; i++) {
                System.out.print(items[i] + " ");
            }
            System.out.print("] ");
            System.out.print("count:" + count + " ");
            System.out.print("in:" + in + " out:" + out + " ");
            System.out.println();
        }
    }
    
    /**
     * 利用锁实现线程同步的buffer
     * 
     * @author jd
     * 
     */
    class LockBuffer extends Buffer {
    
        Lock lock = new ReentrantLock();
        Condition empty = lock.newCondition();
        Condition full = lock.newCondition();
    
        public LockBuffer(int capacity) {
            super(capacity);
        }
    
        public void put(Item item) {
            lock.lock();
    
            try {
                while (count == capacity)
                    full.await();
                items[in] = item;
                in = (in + 1) % capacity;
                count++;
                empty.signal();
    
                System.out.println(Thread.currentThread().getName() + " put item " + item.id);
                printBuf();
    
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
    
            finally {
                lock.unlock();
            }
        }
    
        public Item get() {
            lock.lock();
            Item res = null;
            try {
                while (count == 0)
                    empty.await();
                res = items[out];
                items[out] = null;
                out = (out + 1) % capacity;
                count--;
                full.signal();
    
                System.out.println(Thread.currentThread().getName() + " get item " + res.id);
                printBuf();
    
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
            return res;
        }
    
    }
    
    /**
     * 利用信号量实现的线程同步的buffer
     * 
     * @author jd
     * 
     */
    class SemaphoreBuffer extends Buffer {
        Semaphore mutex;
        Semaphore full;
        Semaphore empty;
    
        public SemaphoreBuffer(int capacity) {
            super(capacity);
            mutex = new Semaphore(1);
            full = new Semaphore(0);
            empty = new Semaphore(capacity);
        }
    
        public void put(Item item) {
    
            try {
                empty.acquire();
                mutex.acquire();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
    
            items[in] = item;
            in = (in + 1) % capacity;
            count++;
    
            System.out.println(Thread.currentThread().getName() + " put item " + item.id);
            printBuf();
    
            mutex.release();
            full.release();
    
        }
    
        public Item get() {
    
            try {
                full.acquire();
                mutex.acquire();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
    
            Item res = items[out];
            items[out] = null;
            out = (out + 1) % capacity;
            count--;
    
            System.out.println(Thread.currentThread().getName() + " get item " + res.id);
            printBuf();
    
            mutex.release();
            empty.release();
            return res;
        }
    
    }
    
    /**
     * 利用同步监视器实现的线程同步的buffer
     * 
     * @author jd
     * 
     */
    class MonitorBuffer extends Buffer {
    
        public MonitorBuffer(int capacity) {
            super(capacity);
        }
    
        public void put(Item item) {
            synchronized (this) {
    
                try {
                    while (count == capacity)
                        wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
    
                items[in] = item;
                in = (in + 1) % capacity;
                count++;
                notifyAll();
    
                System.out.println(Thread.currentThread().getName() + " put item " + item.id);
                printBuf();
    
            }
        }
    
        public Item get() {
            synchronized (this) {
                try {
                    while (count == 0)
                        wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
    
                Item res = items[out];
                items[out] = null;
                out = (out + 1) % capacity;
                count--;
                notifyAll();
    
                System.out.println(Thread.currentThread().getName() + " get item " + res.id);
                printBuf();
                return res;
            }
        }
    }
    
    class Producer implements Runnable {
        Buffer buf;
        Random rand = new Random();
    
        public Producer(Buffer buf) {
            this.buf = buf;
        }
    
        public void run() {
            for (int i = 0; i < 10; i++) {
                Item item = new Item(rand.nextInt(100));
                buf.put(item);
    
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
    
        }
    }
    
    class Consumer implements Runnable {
        Buffer buf;
    
        public Consumer(Buffer buf) {
            this.buf = buf;
        }
    
        public void run() {
            for (int i = 0; i < 10; i++) {
                Item item = buf.get();
    
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    
    public class BoundedBufferTest {
    
        public static void main(String[] args) {
            // Buffer buf = new LockBuffer(5);
            // Buffer buf = new SemaphoreBuffer(5);
            Buffer buf = new MonitorBuffer(5);
    
            // 3个生产者,3个消费者,每个生产或者消费10次。
            for (int i = 0; i < 3; i++) {
                new Thread(new Producer(buf), "p" + i).start();
                new Thread(new Consumer(buf), "c" + i).start();
            }
    
        }
    }
    View Code
     

    读者作家问题

     
    模拟第一读者问题。
    package thread;
    
    import java.util.concurrent.Semaphore;
    
    /**
     * first reader writer problem, writer may starve;
     * 
     * @author jd
     * 
     */
    class Article {
        String content = "The original content.";
        Semaphore mutex, wrt;
        int readCount;
    
        public Article() {
            mutex = new Semaphore(1);
            wrt = new Semaphore(1);
            readCount = 0;
        }
    
        public String read() throws InterruptedException {
            mutex.acquire();
            readCount++;
            if (readCount == 1)
                wrt.acquire();
            mutex.release();
    
            // reading is performed
            String res = content;
            System.out.println(Thread.currentThread().getName() + " is reading, the article is [" + res + "]");
            Thread.sleep(1000);
    
            mutex.acquire();
            readCount--;
            if (readCount == 0)
                wrt.release();
            mutex.release();
    
            return res;
    
        }
    
        public void Write(String str) throws InterruptedException {
            wrt.acquire();
    
            // writing is performed
            content = "new content(" + str + ")";
            System.out.println("content is changed to [" + content + "]");
            Thread.sleep(2000);
    
            wrt.release();
        }
    
    }
    
    class Reader implements Runnable {
        Article art;
    
        public Reader(Article a) {
            art = a;
        }
    
        public void run() {
            try {
                art.read();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    
    class Writer implements Runnable {
        Article art;
    
        public Writer(Article a) {
            art = a;
        }
    
        public void run() {
            try {
                art.Write(Thread.currentThread().getName());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    
    public class ReaderWriterTest {
    
        public static void main(String[] args) {
            Article art = new Article();
    
            for (int i = 0; i < 3; i++) {
                new Thread(new Reader(art), "r" + i).start();
            }
            // writer starves;
            new Thread(new Writer(art), "w").start();
    
            for (int i = 0; i < 3; i++) {
                new Thread(new Reader(art), "rr" + i).start();
            }
    
        }
    }
    View Code

    哲学家吃饭问题

    http://en.wikipedia.org/wiki/Dining_philosophers_problem

    模拟哲学家吃饭问题,该实现可能会产生死锁。

    package thread;
    
    import java.util.concurrent.locks.Lock;
    import java.util.concurrent.locks.ReentrantLock;
    
    /**
     * This version may lead to deadlock.
     * 
     * @author jd
     * 
     */
    class Chopstick {
        private Lock lock = new ReentrantLock();
    
        public void pickUp() {
            lock.lock();
        }
    
        public void putDown() {
            lock.unlock();
        }
    
    }
    
    class Philosopher extends Thread {
        private Chopstick left;
        private Chopstick right;
    
        public Philosopher(Chopstick left, Chopstick right) {
            this.left = left;
            this.right = right;
        }
    
        public void eat() {
            pickUp();
            // eating
            System.out.println(Thread.currentThread().getName() + " is eating");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            putDown();
            System.out.println(Thread.currentThread().getName() + " done eating");
    
        }
    
        public void pickUp() {
            System.out.println(Thread.currentThread().getName() + " is trying to pick up left chopstick..");
            left.pickUp();
    
            // this sleep makes all philosopers pick up left chopstick and try to
            // pick up the right, which leads to a deadlock.
            // this rarely happens, but it can do.
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
    
            System.out.println(Thread.currentThread().getName() + " is trying to pick up right chopstick..");
            right.pickUp();
        }
    
        public void putDown() {
            left.putDown();
            right.putDown();
        }
    
        public void run() {
            eat();
        }
    }
    
    public class DiningPhilosopherTest {
    
        public static void main(String[] args) {
            Chopstick[] chopsticks = new Chopstick[5];
            for (int i = 0; i < 5; i++)
                chopsticks[i] = new Chopstick();
    
            for (int i = 0; i < 5; i++) {
                new Philosopher(chopsticks[i], chopsticks[(i + 1) % 5]).start();
            }
    
        }
    }
    View Code

    不死锁版本,当某个哲学家无法拿到两只筷子时,会主动放弃已有资源(筷子)而放弃本次吃饭。

    package thread;
    
    import java.util.Random;
    import java.util.concurrent.locks.Lock;
    import java.util.concurrent.locks.ReentrantLock;
    
    /**
     * 
     * @author jd
     * 
     */
    class ChopstickNoDeadLock {
        private Lock lock = new ReentrantLock();
    
        public boolean pickUp() {
            return lock.tryLock();
        }
    
        public void putDown() {
            lock.unlock();
        }
    
    }
    
    class PhilosopherNoDeadLock extends Thread {
        Random rand = new Random();
        private ChopstickNoDeadLock left;
        private ChopstickNoDeadLock right;
    
        public PhilosopherNoDeadLock(ChopstickNoDeadLock left, ChopstickNoDeadLock right) {
            this.left = left;
            this.right = right;
        }
    
        public void eat() {
            if (pickUp()) {
                pickUp();
                // eating
                System.out.println(Thread.currentThread().getName() + " is eating");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                putDown();
                System.out.println(Thread.currentThread().getName() + " done eating");
            } else {
                System.out.println(Thread.currentThread().getName() + " gives up eating");
    
            }
        }
    
        public boolean pickUp() {
            System.out.println(Thread.currentThread().getName() + " is trying to pick up left chopstick..");
            if (!left.pickUp()) {
                return false;
            }
    
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
    
            System.out.println(Thread.currentThread().getName() + " is trying to pick up right chopstick..");
            if (!right.pickUp()) {
                left.putDown();
                return false;
            }
    
            return true;
        }
    
        public void putDown() {
            left.putDown();
            right.putDown();
        }
    
        public void run() {
            // for (int i = 0; i < 10; i++) {
            eat();
            // try {
            // Thread.sleep(rand.nextInt(10) * 100);
            // } catch (InterruptedException e) {
            // e.printStackTrace();
            // }
            // }
        }
    }
    
    public class DiningPhilosopherTestNoDeadLock {
    
        public static void main(String[] args) {
            ChopstickNoDeadLock[] chopsticks = new ChopstickNoDeadLock[5];
            for (int i = 0; i < 5; i++)
                chopsticks[i] = new ChopstickNoDeadLock();
    
            for (int i = 0; i < 5; i++) {
                new PhilosopherNoDeadLock(chopsticks[i], chopsticks[(i + 1) % 5]).start();
            }
    
        }
    }
    View Code
  • 相关阅读:
    loj6158 A+B Problem (扩展KMP)
    2017CodeM初赛B场
    Codeforces Round #421(div 2)
    CF821E(多次矩阵快速幂)
    Codechef-ANCESTOR(树套树/CDQ分治)
    Codechef-BLACKCOM(树形背包dp)
    Codechef-CHEFPRAD(找事件点+贪心)
    洛谷 p3391
    luogu p3369
    LOJ10082
  • 原文地址:https://www.cnblogs.com/jdflyfly/p/3973856.html
Copyright © 2011-2022 走看看