0%

1115-交替打印FooBar

前言:学习JUC包后,通过leetcode多线程的题目练习一下,1115-交替打印FooBar

Synchronize

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
public class FooBar {
private int n;
// 可见变量
private volatile boolean flag = true;

public FooBar(int n) {
this.n = n;
}

public void foo(Runnable printFoo) throws InterruptedException {

for (int i = 0; i < n; i++) {
synchronized (this) {
if (!flag) {
// 当前线程等待并释放锁,直到被Notify唤醒重新获得锁
this.wait();
}
printFoo.run();
flag = false;
// 唤醒一个线程
this.notify();
}
}
}

public void bar(Runnable printBar) throws InterruptedException {

for (int i = 0; i < n; i++) {
synchronized (this) {
if(flag){
// 当前线程等待并释放锁,直到被Notify唤醒重新获得锁
this.wait();
}
printBar.run();
flag = true;
// 唤醒一个线程
this.notify();
}
}
}
}

Semaphore

使用两个信号量,一个初始化为1,另一个初始化为0。执行方法时获取自己的信号量释放对方的信号量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public class FooBar {
private int n;
private Semaphore fooSp = new Semaphore(1);
private Semaphore barSp = new Semaphore(0);

public FooBar(int n) {
this.n = n;
}

public void foo(Runnable printFoo) throws InterruptedException {

for (int i = 0; i < n; i++) {
fooSp.acquire();
printFoo.run();
barSp.release();
}
}

public void bar(Runnable printBar) throws InterruptedException {

for (int i = 0; i < n; i++) {
barSp.acquire();
printBar.run();
fooSp.release();
}
}
}

cyclicBarrier

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
/**
* @author shency
* @description: TODO
* @date: 2019/12/3
*/
public class FooBar {
private int n;
private CyclicBarrier cyclicBarrier = new CyclicBarrier(2);
// flag==true执行foo,false执行bar
private volatile boolean flag = true;

public FooBar(int n) {
this.n = n;
}

public void foo(Runnable printFoo) throws InterruptedException {

for (int i = 0; i < n; i++) {
while (!flag);
printFoo.run();
flag = false;
try {
cyclicBarrier.await();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}

}
}

public void bar(Runnable printBar) throws InterruptedException {

for (int i = 0; i < n; i++) {
try {
cyclicBarrier.await();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
printBar.run();
flag = true;
}
}
}

管程

管程 (Moniters,也称为监视器) 是一种程序结构,结构内的多个子程序(对象或模块)形成的多个工作线程互斥访问共享资源。管程实现了在一个时间点,最多只有一个线程在执行管程的某个子程序,线程可以临时放弃互斥锁,等待某些条件得到满足后,重新获得执行权恢复它的互斥锁。

一个管程包含:

  • 多个彼此可以交互并共用资源的线程
  • 多个与资源使用有关的变量
  • 一个互斥锁
  • 一个用来避免竞态条件的不变量
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
public class FooBar {
private int n;
// flag==true执行foo,false执行bar
private volatile boolean flag = true;
private ReentrantLock lock = new ReentrantLock();
private Condition foo = lock.newCondition();
private Condition bar = lock.newCondition();

public FooBar(int n) {
this.n = n;
}

public void foo(Runnable printFoo) throws InterruptedException {
for (int i = 0; i < n; i++) {
lock.lock();
try {
while (!flag) {
foo.await();
}
printFoo.run();
flag = false;
bar.signal();
} finally {
lock.unlock();
}
}
}

public void bar(Runnable printBar) throws InterruptedException {

for (int i = 0; i < n; i++) {
lock.lock();
try {
while (flag) {
bar.await();
}
printBar.run();
flag = true;
foo.signal();
} finally {
lock.unlock();
}
}
}
}
-------------本文结束感谢您的阅读-------------