前言:学习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) { 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){ 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
|
public class FooBar { private int n; private CyclicBarrier cyclicBarrier = new CyclicBarrier(2); 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; 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(); } } } }
|