在Doug lea的那本著名的《Java並發編程—設計原則與模式》
英文名
Concurrent Programming in Java;: Design Principles and Patterns Second Edition書中提到可以用信號量Semaphore實現互斥鎖Mutex
雖然java中是通過synchronize關鍵字提供鎖
並用這個基礎設施實現信號量的
在有的系統中只有信號量這一原語
鎖是通過信號量實現的
代碼如下

import ncurrent
Semaphore;



public class Mutex
{

private Semaphore s = new Semaphore(
);



public void acquire() throws InterruptedException
{

s
acquire();

}


public void release()
{

s
release();

}


public boolean attempt(int ms) throws InterruptedException
{

return s
tryAcquire(ms);

}

}

上面的代碼只能在java
中編譯通過
因為Semaphore是在java
中才提供的
我在讀上面的代碼時有疑問
因為如果錯誤的連續調用release兩次
然後兩個線程都調用acquire
豈不是這兩個線程都可以同時運行
從而違背了互斥鎖的定義?為了證明我的猜測
寫了如下的代碼


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 e
)
{

throw new RuntimeException(e
);

}


for(int i=
;i<
;i++)
{

System
out
print(i);


if(i%
==
)
{


try
{

Thread
sleep(
);


} catch (InterruptedException e)
{

e
printStackTrace();

}

}

}

mutex
release();

}

}
該程序的輸出如下
從而證實了我的猜測
作為對比下面是采用synchronized關鍵字的互斥鎖方案


public class TestLock
{


public static void main(String[] args) throws InterruptedException
{

new MyThread
()
start();

new MyThread
()
start();

}


}



class MyThread
extends Thread
{


public void run()
{


synchronized(TestLock
class)
{


for(int i=
;i<
;i++)
{

System
out
print(i);


if(i%
==
)
{


try
{

Thread
sleep(
);


} catch (InterruptedException e)
{

e
printStackTrace();

}

}

}

}

}

}
該程序的輸出如下
可見兩個線程確實互斥運行
這個問題產生的原因是雖然在Mutex的定義中private Semaphore s = new Semaphore()也就是該信號量的初始permits是但是在此後每次調用release方法都會導致permits加一如果能限制permits最大值最小值那就是真正的Mutex了
From:http://tw.wingwit.com/Article/program/Java/hx/201311/26275.html