Skip to content

Commit c5bf817

Browse files
committed
semaphore
1 parent e04a5fe commit c5bf817

File tree

4 files changed

+79
-14
lines changed

4 files changed

+79
-14
lines changed

src/main/java/io/concurrency/chapter06/exam02/BinarySemaphore.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ public synchronized void acquired() {
1515
}
1616

1717
public synchronized void release() {
18-
this.signal = 1;
19-
this.notify();
18+
this.signal = 1; //다른 스레드들이 사용 가능함을 설정
19+
this.notify(); // 모든 대기 스레드 중 임의로 선택한 스레드 하나만 깨움.
2020
}
2121
}

src/main/java/io/concurrency/chapter06/exam02/CountingSemaphore.java

+24-10
Original file line numberDiff line numberDiff line change
@@ -9,20 +9,34 @@ public CountingSemaphore(int permits) {
99
this.signal = permits;
1010
}
1111

12-
public void acquired() {
13-
synchronized (this) {
14-
while (this.signal == 0) {
15-
try {
16-
wait();
17-
} catch (InterruptedException e) {
18-
e.printStackTrace();
19-
}
12+
13+
public synchronized void acquired(){
14+
while(this.signal==0){
15+
try {
16+
wait();
17+
} catch (InterruptedException e) {
18+
throw new RuntimeException(e);
2019
}
21-
this.signal--;
2220
}
23-
System.out.println(Thread.currentThread().getName() + " 락 획득, 현재 세마포어 값: " + signal);
21+
this.signal--;
22+
System.out.println(Thread.currentThread().getName() + ": 락 획득, 현재 세마포어 값: "+signal);
2423
}
2524

25+
// public void acquired() {
26+
// synchronized (this) {
27+
// while (this.signal == 0) {
28+
// try {
29+
// wait();
30+
// } catch (InterruptedException e) {
31+
// e.printStackTrace();
32+
// }
33+
// }
34+
// this.signal--;
35+
// }
36+
// System.out.println(Thread.currentThread().getName() + " 락 획득, 현재 세마포어 값: " + signal);
37+
// }
38+
39+
2640
public synchronized void release() {
2741
if (this.signal < permits) { // signal 값이 permits 보다 작을 때만 증가
2842
this.signal++;

src/main/java/io/concurrency/chapter06/exam02/CountingSemaphoreExample.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@
33
public class CountingSemaphoreExample {
44
public static void main(String[] args) {
55

6-
int permits = 10; // 최대 3개의 스레드가 동시에 작업을 수행할 수 있습니다.
6+
int permits = 3; // 최대 3개의 스레드가 동시에 작업을 수행할 수 있습니다.
77
CountingSemaphore semaphore = new CountingSemaphore(permits);
88
SharedResource resource = new SharedResource(semaphore);
99

10-
int threadCount = 5; // 전체 스레드 개수
10+
int threadCount = 10; // 전체 스레드 개수
1111

1212
Thread[] threads = new Thread[threadCount];
1313
for (int i = 0; i < threadCount; i++) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
## Semaphore
2+
3+
- 세마포어: 공유 자원에 대한 접근 제어를 위한 신호 전달 메커니즘 동기화 도구
4+
- S: 공유 자원 개수
5+
- S > 0 -> 공유 자원 접근 허용
6+
- S <= 0 -> 공유 자원 접근 거부
7+
- P: 스레드 진입 여부 결정 (wait 연산)
8+
- V: 대기 중인 스레드를 깨우는 (signal 연산) <br>
9+
10+
---> 같은 세마포어의 P,V 함수의 S 연산은 원자적 실행이 보장되어야 한다(보장된다)
11+
12+
13+
Mutex는 락을 획득하고 해제한 스레드가 동일해야 하지만<br>
14+
Semaphore는 락을 획득하고 해제한 스레드가 같지 않아도 된다
15+
16+
Mutex는 기본적으로 잠긴 상태로 초기 시작되지만, 세마포어는 초기값 설정을 통해 공유 자원에 몇 개의 동시 스레드를 허용할 것인지 설정할 수 있다
17+
18+
이진 세마포어를 구현한다면 Mutex와 동일하게 구현 가능
19+
20+
Mutex가 상호 배제 목적에 더 부합하고, Semaphore는 주로 리소스의 한정적 사용을 제한하는데 부합하다
21+
22+
23+
ex) 이진 세마포어
24+
25+
```java
26+
public class BinarySemaphore implements CommonSemaphore {
27+
private int signal = 1;
28+
29+
public synchronized void acquired() {
30+
while (this.signal == 0) {
31+
try {
32+
wait();
33+
} catch (InterruptedException e) {
34+
Thread.currentThread().interrupt(); // 현재 스레드의 인터럽트 상태를 설정
35+
}
36+
}
37+
this.signal = 0;
38+
}
39+
40+
public synchronized void release() {
41+
this.signal = 1; //다른 스레드들이 사용 가능함을 설정
42+
this.notify(); // 모든 대기 스레드 중 임의로 선택한 스레드 하나만 깨움.
43+
}
44+
}
45+
```
46+
47+
synchronized가 붙은 메서드가 호출되면 해당 객체의 다른 synchronized가 붙은 어떤 메서드들도 호출될 수 없다
48+
따라서 release()의 원자적 실행이 보장되며, 이는 V연산(signal)의 원자적 실행을 보장하는 것이다
49+
임계 영역을 끝낸 스레드는 acquired()에 의해 wait 중인 대기 스레드들 중 하나를 notify()함으로써 다른 스레드의 진입을 허용한다
50+
51+

0 commit comments

Comments
 (0)