本文学习信号量Semaphore机制。
下面通过以前的获取苹果的价格的列子来演示信号量的使用
public class Client {
public static void main(String[] args) {
final GoodInfo gi = new GoodInfo();
Thread[] read = new Thread[10]; //读线程,读取10次商品信息
for (int i = 0; i < 10; i++) {
read[i] = new Thread(new Runnable() {
@Override
public void run() {
gi.getInfo();
}
});
}
final Thread[] write = new Thread[3]; //写线程,修改3次价格
for (int i = 0; i < 3; i++) {
final int finalI = i;
write[i] = new Thread(new Runnable() {
@Override
public void run() {
gi.setPrice();
}
});
}
for (Thread t : write) {
t.start();
}
for (Thread t : read) {
t.start();
}
}
}
/** 商品信息类 */
class GoodInfo {
private String name = "苹果"; //商品名称
private double price = 10; //商品价格
private final Semaphore sh = new Semaphore(3); //申请3个信号量
/**
* 读取商品信息
*
* @return
*/
public void getInfo() {
try {
sh.acquire(1); //获取1个信号量,如果不够,则当前线程等待
String name = this.name;
double price = this.price;
System.out.println(Thread.currentThread().getName() + "线程获取了商品信息:" + name + ":" + price);
} catch (Exception e) {
e.printStackTrace();
} finally {
sh.release(); //释放信号量
}
}
/**
* 修改商品价格,每次都自增1
*
*/
public void setPrice() {
try {
sh.acquire(1);
this.price = this.price + 1; //目的是:多个线程并发的时候会出现错误数据(数据竞争来验证获取了信号量的线程是并发线程)
System.out.println("--------------" + Thread.currentThread().getName() + "线程修改了商品价格:" + name + ":" + price);
Thread.sleep(20);
} catch (Exception e) {
e.printStackTrace();
} finally {
sh.release(); //如果把这里注释掉,则可以看出,其他等待获取信号量的是获取不到信号量了。因为一单这里的三个线程把可用的信号量占用完之后,其他线程就只能等待可用的信号量了
}
}
}
某一次的运行结果:
--------------Thread-11线程修改了商品价格:苹果:11.0
Thread-5线程获取了商品信息:苹果:10.0
Thread-7线程获取了商品信息:苹果:11.0
Thread-0线程获取了商品信息:苹果:11.0
Thread-1线程获取了商品信息:苹果:11.0
Thread-2线程获取了商品信息:苹果:11.0
Thread-4线程获取了商品信息:苹果:11.0
Thread-3线程获取了商品信息:苹果:11.0
--------------Thread-10线程修改了商品价格:苹果:12.0
Thread-6线程获取了商品信息:苹果:12.0
--------------Thread-12线程修改了商品价格:苹果:13.0
Thread-8线程获取了商品信息:苹果:13.0
Thread-9线程获取了商品信息:苹果:13.0
如果把写价格的释放信号量注释掉,运行结果是
--------------Thread-12线程修改了商品价格:苹果:11.0
Thread-8线程获取了商品信息:苹果:10.0
Thread-0线程获取了商品信息:苹果:11.0
Thread-4线程获取了商品信息:苹果:11.0
Thread-2线程获取了商品信息:苹果:11.0
Thread-3线程获取了商品信息:苹果:11.0
Thread-1线程获取了商品信息:苹果:11.0
Thread-6线程获取了商品信息:苹果:11.0
Thread-5线程获取了商品信息:苹果:11.0
Thread-7线程获取了商品信息:苹果:11.0
--------------Thread-10线程修改了商品价格:苹果:12.0
--------------Thread-11线程修改了商品价格:苹果:13.0
线程没有运行完,没有获取到信号量的线程,则一直等待。造成了死锁。
说明
上面的运行结果可以看出来:
线程11修改了商品结果,但是线程5和线程11 并发的获取了原有的价格10,导致了线程5获取到了错误的数据信息。
把以上示例的 构造信号量对象的参数置为1
new Semaphore(1); /创建二进制信号量
某一次的运行结果是
--------------Thread-10线程修改了商品价格:苹果:11.0
--------------Thread-11线程修改了商品价格:苹果:12.0
Thread-1线程获取了商品信息:苹果:12.0
Thread-2线程获取了商品信息:苹果:12.0
Thread-5线程获取了商品信息:苹果:12.0
Thread-6线程获取了商品信息:苹果:12.0
Thread-9线程获取了商品信息:苹果:12.0
--------------Thread-12线程修改了商品价格:苹果:13.0
Thread-0线程获取了商品信息:苹果:13.0
Thread-4线程获取了商品信息:苹果:13.0
Thread-3线程获取了商品信息:苹果:13.0
Thread-7线程获取了商品信息:苹果:13.0
Thread-8线程获取了商品信息:苹果:13.0
可以看出来,而互斥锁的效果一致。
而这个类的使用场景。我暂时还没想明白。为什么有这样的机制。至于公平信号量和非公平信号量就不演示了。很简单的。知道互斥锁和信号量的区别是什么就行了
版权声明:本文为博主原创文章,未经博主允许不得转载。
[笔记][Java7并发编程实战手册]3.2 资源的并发访问控制Semaphore信号量
原文:http://blog.csdn.net/mr_zhuqiang/article/details/47622621