2020年11月10日 面试蚂蚁金服时遇到的原题,可以用多种同步实现,适合拿出来热身。

自旋

  1. class FooBar {
  2. private int n;
  3. public FooBar(int n) {
  4. this.n = n;
  5. }
  6. volatile boolean permitFoo = true;
  7. public void foo(Runnable printFoo) throws InterruptedException {
  8. for (int i = 0; i < n; ) {
  9. if(permitFoo) {
  10. printFoo.run();
  11. i++;
  12. permitFoo = false;
  13. }else{
  14. Thread.yield();
  15. }
  16. }
  17. }
  18. public void bar(Runnable printBar) throws InterruptedException {
  19. for (int i = 0; i < n; ) {
  20. if(!permitFoo) {
  21. printBar.run();
  22. i++;
  23. permitFoo = true;
  24. }else{
  25. Thread.yield();
  26. }
  27. }
  28. }
  29. }

synchronized

  1. class FooBar {
  2. private int n;
  3. public FooBar(int n) {
  4. this.n = n;
  5. }
  6. // 标志位,控制执行顺序,true执行printFoo,false执行printBar
  7. private volatile boolean type = true;
  8. private final Object foo= new Object(); // 锁标志
  9. public void foo(Runnable printFoo) throws InterruptedException {
  10. for (int i = 0; i < n; i++) {
  11. synchronized (foo) {
  12. while(!type){
  13. foo.wait();
  14. }
  15. printFoo.run();
  16. type = false;
  17. foo.notifyAll();
  18. }
  19. }
  20. }
  21. public void bar(Runnable printBar) throws InterruptedException {
  22. for (int i = 0; i < n; i++) {
  23. synchronized (foo) {
  24. while(type){
  25. foo.wait();
  26. }
  27. printBar.run();
  28. type = true;
  29. foo.notifyAll();
  30. }
  31. }
  32. }
  33. }

可重入锁

  1. class FooBar {
  2. private int n;
  3. public FooBar(int n) {
  4. this.n = n;
  5. }
  6. Lock lock = new ReentrantLock(true);
  7. private final Condition foo = lock.newCondition();
  8. volatile boolean flag = true;
  9. public void foo(Runnable printFoo) throws InterruptedException {
  10. for (int i = 0; i < n; i++) {
  11. lock.lock();
  12. try {
  13. while(!flag) {
  14. foo.await();
  15. }
  16. printFoo.run();
  17. flag = false;
  18. foo.signal();
  19. } finally {
  20. lock.unlock();
  21. }
  22. }
  23. }
  24. public void bar(Runnable printBar) throws InterruptedException {
  25. for (int i = 0; i < n;i++) {
  26. lock.lock();
  27. try {
  28. while(flag) {
  29. foo.await();
  30. }
  31. printBar.run();
  32. flag = true;
  33. foo.signal();
  34. } finally {
  35. lock.unlock();
  36. }
  37. }
  38. }
  39. }

循环栅栏

  1. class FooBar {
  2. private int n;
  3. public FooBar(int n) {
  4. this.n = n;
  5. }
  6. CyclicBarrier cb = new CyclicBarrier(2);
  7. volatile boolean fin = true;
  8. public void foo(Runnable printFoo) throws InterruptedException {
  9. for (int i = 0; i < n; i++) {
  10. while(!fin);
  11. printFoo.run();
  12. fin = false;
  13. try {
  14. cb.await();
  15. } catch (BrokenBarrierException e) {}
  16. }
  17. }
  18. public void bar(Runnable printBar) throws InterruptedException {
  19. for (int i = 0; i < n; i++) {
  20. try {
  21. cb.await();
  22. } catch (BrokenBarrierException e) {}
  23. printBar.run();
  24. fin = true;
  25. }
  26. }
  27. }

信号量

  1. class FooBar {
  2. private int n;
  3. public FooBar(int n) {
  4. this.n = n;
  5. }
  6. private Semaphore foo = new Semaphore(1);
  7. private Semaphore bar = new Semaphore(0);
  8. public void foo(Runnable printFoo) throws InterruptedException {
  9. for (int i = 0; i < n; i++) {
  10. foo.acquire();
  11. printFoo.run();
  12. bar.release();
  13. }
  14. }
  15. public void bar(Runnable printBar) throws InterruptedException {
  16. for (int i = 0; i < n; i++) {
  17. bar.acquire();
  18. printBar.run();
  19. foo.release();
  20. }
  21. }
  22. }

阻塞队列

  1. public class FooBar {
  2. private int n;
  3. private BlockingQueue<Integer> bar = new LinkedBlockingQueue<>(1);
  4. private BlockingQueue<Integer> foo = new LinkedBlockingQueue<>(1);
  5. public FooBar(int n) {
  6. this.n = n;
  7. }
  8. public void foo(Runnable printFoo) throws InterruptedException {
  9. for (int i = 0; i < n; i++) {
  10. foo.put(i);
  11. printFoo.run();
  12. bar.put(i);
  13. }
  14. }
  15. public void bar(Runnable printBar) throws InterruptedException {
  16. for (int i = 0; i < n; i++) {
  17. bar.take();
  18. printBar.run();
  19. foo.take();
  20. }
  21. }
  22. }

参考文献