Skip to content

Commit 740ac89

Browse files
committed
信号量替代互斥锁提升写互斥读线程安全情境下的操作吞吐量
1 parent f66686d commit 740ac89

File tree

1 file changed

+83
-0
lines changed

1 file changed

+83
-0
lines changed
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
package concurrent.shared;
2+
3+
import java.util.concurrent.*;
4+
5+
/**
6+
* 目的,在添加数据操作需要互斥、全部任务为读取时是线程安全的情况下,
7+
* 可以使用Semaphore的公平锁来提高吞吐量,而非使用互斥锁。思路是读取时
8+
* 仅仅获取一个许可,而添加数据时获取全部许可。
9+
*
10+
* 注意:
11+
* 没有获取许可也能释放许可—相应的statu+1。但是释放后的总许可数量不能超过Integer.MAX_VALUE;
12+
* int next = current + releases;
13+
* if (next < current) // overflow
14+
* throw new Error("Maximum permit count exceeded");
15+
*
16+
* 结论:ok
17+
*
18+
* @author 杜艮魁
19+
* @date 2018/10/9
20+
*/
21+
public class SemaphoreTest {
22+
/**
23+
* 注意一定要用公平锁,非公平锁在高并发情况下会导致put任务难以执行
24+
*/
25+
private static final Semaphore sem = new Semaphore(Integer.MAX_VALUE, true);
26+
27+
public static void main(String[] args) throws InterruptedException {
28+
29+
// 结论1
30+
// sem.release();
31+
// System.out.println(sem.availablePermits());
32+
33+
/**
34+
* 需一个许可的读取任务
35+
*/
36+
Runnable getTask = () -> {
37+
try {
38+
sem.acquire();//默认获取一个许可
39+
for (int i = 0; i < 5; i++) {
40+
System.out.println("getting data " + Thread.currentThread().getName() + "..."+i);
41+
TimeUnit.SECONDS.sleep(1);
42+
}
43+
} catch (InterruptedException e) {
44+
} finally {
45+
sem.release();
46+
}
47+
};
48+
49+
/**
50+
* 需全部Integer.MAX_VALUE许可的添加数据任务
51+
*/
52+
Runnable putTask = () -> {
53+
try {
54+
sem.acquire(Integer.MAX_VALUE);
55+
for (int i = 0; i < 5; i++) {
56+
System.out.println("putting data " + Thread.currentThread().getName() + "..."+i);
57+
TimeUnit.SECONDS.sleep(1);
58+
}
59+
} catch (InterruptedException e) {
60+
} finally {
61+
sem.release(Integer.MAX_VALUE);
62+
}
63+
};
64+
65+
66+
/**
67+
* 模拟这种情形,前两个线程并发执行读取任务,第三个线程put阻塞,此时第四个任务也会阻塞,会等待第三个任务执行结束后再执行
68+
*/
69+
ExecutorService es= Executors.newCachedThreadPool();
70+
es.submit(getTask);
71+
TimeUnit.MILLISECONDS.sleep(10);
72+
73+
es.submit(getTask);
74+
TimeUnit.MILLISECONDS.sleep(10);
75+
76+
es.submit(putTask);
77+
TimeUnit.MILLISECONDS.sleep(10);
78+
79+
es.submit(getTask);
80+
81+
es.shutdown();
82+
}
83+
}

0 commit comments

Comments
 (0)