信號(hào)量Semaphore實(shí)現(xiàn)互斥鎖Mutex

字號(hào):

在Doug lea的那本的《Java并發(fā)編程—設(shè)計(jì)原則與模式》,英文名" Concurrent Programming in Java™: Design Principles and Patterns, Second Edition",書(shū)中提到可以用信號(hào)量Semaphore實(shí)現(xiàn)互斥鎖Mutex。雖然java中是通過(guò)synchronize關(guān)鍵字提供鎖,并用這個(gè)基礎(chǔ)設(shè)施實(shí)現(xiàn)信號(hào)量的。在有的系統(tǒng)中只有信號(hào)量這一原語(yǔ),鎖是通過(guò)信號(hào)量實(shí)現(xiàn)的。代碼如下:
    import java.util.concurrent.Semaphore;
    public class Mutex ...{
     private Semaphore s = new Semaphore(1);
     public void acquire() throws InterruptedException ...{
     s.acquire();
     }
     public void release()...{
     s.release();
     }
     public boolean attempt(int ms) throws InterruptedException ...{
     return s.tryAcquire(ms);
     }
    }
    上面的代碼只能在java5中編譯通過(guò),因?yàn)镾emaphore是在java5中才提供的。我在讀上面的代碼時(shí)有疑問(wèn)。因?yàn)槿绻e(cuò)誤的連續(xù)調(diào)用release兩次,然后兩個(gè)線程都調(diào)用acquire,豈不是這兩個(gè)線程都可以同時(shí)運(yùn)行,從而違背了互斥鎖的定義?為了證明我的猜測(cè),寫(xiě)了如下的代碼:
    public class TestMutex ...{
     public static void main(String[] args) throws InterruptedException...{
     Mutex mutex=new Mutex();
     mutex.acquire();
     mutex.release();
     mutex.release();
     new MyThread(mutex).start();
     new MyThread(mutex).start();
     }
    }
    class MyThread extends Thread...{
     private Mutex mutex;
     public MyThread(Mutex mutex) ...{
     this.mutex=mutex;
     }
     public void run()...{
     try ...{
     mutex.acquire();
     } catch (InterruptedException e1) ...{
     throw new RuntimeException(e1);
     }
     for(int i=0;i<10;i++)...{
     System.out.print(i);
     if(i%3==0)...{
     try ...{
     Thread.sleep(100);
     } catch (InterruptedException e) ...{
     e.printStackTrace();
     }
     }
     }
     mutex.release();
     }
    }
    該程序的輸出如下:
    00123123456456789789
    從而證實(shí)了我的猜測(cè)。