Java: Semaphore is used to protect access to multiple shared resources. semaphore shares resources.

Source: Internet
Author: User

Java: Semaphore is used to protect access to multiple shared resources. semaphore shares resources.

The semaphore mechanism is a common synchronization mechanism, which is widely used in modern OS. Semaphore is a non-zero value. When its value is greater than 0, it indicates that the system still has enough resources allocated to the request thread. Each time a resource is allocated, the value decreases. If the value is equal to 0, no resources can be allocated. JDK providesSemaphoreClass.

If we have a total of three printers available, there are currently N threads requesting the use of printers, to achieve access protection for printer resources, there are two ways:

Obviously, when only one thread can use the printer at a certain time point, the other two printer resources will be wasted. Some may think that if you only lock the code for checking and assigning the printer, but do not lock the printer, when the first thread uses the printer, the second thread can still request the printer. can I allow the three threads to use the printer?

This is very dangerous. We call it a resource.Escape. If the printer is not locked, if the request thread allocates the escaped printer to other threads, the thread synchronization will be meaningless.

For method 2, when thread A uses the printer, thread B can still request and use the printer, and thread C can also. After thread A is used up, semaphore must be released so that other threads can use this printer again.

First, define the printer object:

class Printer {    private String name;    private int index;    public Printer(String name, int index) {        this.name = name;        this.index = index;    }    public void print() {        System.out.println("printer " + name + " is working for " + Thread.currentThread().getName());        try {            Thread.currentThread().sleep(10);        } catch (InterruptedException e) {            e.printStackTrace();        }        System.out.println("printer " + name + " for " + Thread.currentThread().getName() + " is done");    }    public int getIndex() {        return this.index;    }}

Then, we define a printer Pool ). Use this pool to securely allocate printer resources:

class PrinterPool {    /**     * store all available devices     */    private Printer[] printers;    private boolean[] freePrinters;    private Lock lock = new ReentrantLock();    /**     * create a semaphore for 3 resources     */    private Semaphore semaphore = new Semaphore(3);    /**     * 3 printers available in this pool.     */    public PrinterPool() {        printers = new Printer[] {                new Printer("A", 0),                new Printer("B", 1),                new Printer("C", 2)        };        freePrinters = new boolean[] {                true,                true,                true        };    }    /**     * use printer     */    public Printer printData() {        Printer printer = null;        try {            semaphore.acquire();            while (true) {                printer = getFreePrinter();                if (printer != null) {                    break;                }            }            // use printer            printer.print();            // reclaim printer            reclaimPrinter(printer);        } catch (InterruptedException e) {            e.printStackTrace();        } finally {            semaphore.release();        }        return printer;    }    private Printer getFreePrinter() {        Printer printer = null;        lock.lock();        for (int ix = 0 ; ix < freePrinters.length ; ++ix) {            if (true == freePrinters[ix]) {                freePrinters[ix] = false;                printer = printers[ix];                break;            }        }        lock.unlock();        return printer;    }    private void reclaimPrinter(Printer p) {        lock.lock();        this.freePrinters[p.getIndex()] = true;        lock.unlock();    }}

Finally, write the test code and start 10 threads to request the printer:

// create printer pool        PrinterPool pool = new PrinterPool();        Runnable job = () -> {            pool.printData();        };        // create 10 threads        Thread[] threads = new Thread[10];        for (int ix = 0 ; ix < 10 ; ++ix) {            threads[ix] = new Thread(job);        }        // start all threads        for (int ix = 0 ; ix < 10 ; ++ix) {            threads[ix].start();        }

Output result:

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.