Java中在控制多线程访问资源的时候使用了信号量可以控制多个线程同时访问一个资源。
有两个构造方法:
public Semaphore(int permits)
public Semaphore(int permits,boolean fair)
第二个参数和重入锁一样,是指定是否公平。(公平是要牺牲性能的)
1 public class SignalNum implements Runnable { 2 Semaphore semaphore=new Semaphore(2); 3 4 5 @Override 6 public void run() { 7 try { 8 semaphore.acquire(); 9 for(int i=1;i<10;i++){ 10 Thread.sleep(2000); 11 System.out.println(Thread.currentThread().getName()+":done"+i); 12 } 13 14 semaphore.release(); 15 } catch (InterruptedException e) { 16 e.printStackTrace(); 17 } 18 } 19 20 public static void main(String[] args){ 21 SignalNum signalNum=new SignalNum(); 22 Thread t1=new Thread(signalNum,"t1"); 23 Thread t2=new Thread(signalNum,"t2"); 24 Thread t3=new Thread(signalNum,"t3"); 25 26 t1.start(); 27 t2.start(); 28 t3.start(); 29 } 30 }
这个例子的是指定了一次可以运行2的信号量,之后的执行结果为:
D:\Java\jdk1.7.0_45\bin\java -Didea.launcher.port=7535 "-Didea.launcher.bin.path=D:\Program Files (x86)\JetBrains\IntelliJ IDEA 15.0.4\bin" -Dfile.encoding=UTF-8 -classpath "D:\Java\jdk1.7.0_45\jre\lib\charsets.jar;D:\Java\jdk1.7.0_45\jre\lib\deploy.jar;D:\Java\jdk1.7.0_45\jre\lib\ext\access-bridge-64.jar;D:\Java\jdk1.7.0_45\jre\lib\ext\dnsns.jar;D:\Java\jdk1.7.0_45\jre\lib\ext\jaccess.jar;D:\Java\jdk1.7.0_45\jre\lib\ext\localedata.jar;D:\Java\jdk1.7.0_45\jre\lib\ext\sunec.jar;D:\Java\jdk1.7.0_45\jre\lib\ext\sunjce_provider.jar;D:\Java\jdk1.7.0_45\jre\lib\ext\sunmscapi.jar;D:\Java\jdk1.7.0_45\jre\lib\ext\zipfs.jar;D:\Java\jdk1.7.0_45\jre\lib\javaws.jar;D:\Java\jdk1.7.0_45\jre\lib\jce.jar;D:\Java\jdk1.7.0_45\jre\lib\jfr.jar;D:\Java\jdk1.7.0_45\jre\lib\jfxrt.jar;D:\Java\jdk1.7.0_45\jre\lib\jsse.jar;D:\Java\jdk1.7.0_45\jre\lib\management-agent.jar;D:\Java\jdk1.7.0_45\jre\lib\plugin.jar;D:\Java\jdk1.7.0_45\jre\lib\resources.jar;D:\Java\jdk1.7.0_45\jre\lib\rt.jar;E:\JavaIDEA\TestJavaThread\out\test\test;D:\Program Files (x86)\JetBrains\IntelliJ IDEA 15.0.4\lib\idea_rt.jar" com.intellij.rt.execution.application.AppMain SignalNum
t1:done1
t2:done1
t1:done2
t2:done2
t1:done3
t2:done3
t1:done4
t2:done4
t1:done5
t2:done5
t1:done6
t2:done6
t1:done7
t2:done7
t1:done8
t2:done8
t1:done9
t2:done9
t3:done1
t3:done2
t3:done3
t3:done4
t3:done5
t3:done6
t3:done7
t3:done8
t3:done9
Process finished with exit code 0
我们可以看到t1 t2两个线程可以执行,然后t3等到了两个线程执行完成之后才能执行。
信号量是用来同步数据的。
然而在同时获得的资源会不会线程安全呢?我做了测试让3个线程同时获得资源然后各自加10000次,我发现了会有小于30000次的情况,说明同时获得资源的线程是线程不安全的,所以就算使用了信号量,还是要加锁。在这里我认为使用重入锁更加恰当,如果使用synchronized那么同时获得资源就没有意义了。