1、线程通信-交替操作sync实现

变量初始值为0
a线程对变量进行++操作后,通知b线程对变量进行—操作
b线程对变量进行—操作后,通知a线程对变量进行++操作
使用synchronized与Lock两种方式实现。
synchronized代码实现:

  1. class STicket{
  2. private int target=0;
  3. public synchronized void incr(){
  4. if(target!=0){
  5. try {
  6. //等待其他线程进行操作
  7. this.wait();
  8. } catch (InterruptedException e) {
  9. e.printStackTrace();
  10. }
  11. }
  12. target++;
  13. System.out.println(Thread.currentThread().getName()+"::"+target);
  14. //操作完毕后,唤醒其他线程进行操作
  15. this.notifyAll();
  16. }
  17. public synchronized void decr(){
  18. if(target!=1){
  19. try {
  20. this.wait();
  21. } catch (InterruptedException e) {
  22. e.printStackTrace();
  23. }
  24. }
  25. target--;
  26. System.out.println(Thread.currentThread().getName()+"::"+target);
  27. this.notifyAll();
  28. }
  29. }
  30. public class SyncTest {
  31. public static void main(String[] args) {
  32. STicket ticket=new STicket();
  33. new Thread(()->{
  34. for (int i=0;i<10;i++){
  35. ticket.incr();
  36. }
  37. },"线程1").start();
  38. new Thread(()->{
  39. for (int i=0;i<10;i++){
  40. ticket.decr();
  41. }
  42. },"线程2").start();
  43. }
  44. }

2、线程通信synchronized虚假唤醒

创建线程3:对target进行++操作
创建线程4:对target进行—操作
虚假唤醒情况说明:当线程1对target操作完毕后target=1,恰好此时线程3抢到执行权,此时线程3进入等待状态target=1,此时线程2抢到执行权对target进行操作后target=0,线程1再次抢到执行权操作完毕后唤醒线程target=1,刚好被线程3抢到执行权进行++后,此时target=2,同理—操作也如此。

解决方案:将 if 判断修改为 while 循环

  1. while(target!=0){
  2. this.wait();//异常处理省略
  3. }
  4. while(target!=1){
  5. this.wait();
  6. }

3、线程通信-交替操作Lock实现

  1. class Share {
  2. private int target = 0;
  3. private Lock lock = new ReentrantLock();
  4. private Condition condition = lock.newCondition();
  5. public void incr() throws InterruptedException {
  6. lock.lock();
  7. try {
  8. while (target != 0) {
  9. //等待其他线程进行操作
  10. condition.await();
  11. }
  12. target++;
  13. System.out.println(Thread.currentThread().getName() + "::" + target);
  14. //唤醒其他线程
  15. condition.signalAll();
  16. } finally {
  17. lock.unlock();
  18. }
  19. }
  20. public void decr() throws InterruptedException {
  21. lock.lock();
  22. try {
  23. while (target != 1) {
  24. condition.await();
  25. }
  26. target--;
  27. System.out.println(Thread.currentThread().getName() + "::" + target);
  28. condition.signalAll();
  29. } finally {
  30. lock.unlock();
  31. }
  32. }
  33. }
  34. public class LockDemo {
  35. public static void main(String[] args) {
  36. Share share = new Share();
  37. new Thread(() -> {
  38. for (int i = 0; i < 10; i++) {
  39. try {
  40. share.incr();
  41. } catch (InterruptedException e) {
  42. e.printStackTrace();
  43. }
  44. }
  45. }, "线程1").start();
  46. new Thread(() -> {
  47. for (int i = 0; i < 10; i++) {
  48. try {
  49. share.decr();
  50. } catch (InterruptedException e) {
  51. e.printStackTrace();
  52. }
  53. }
  54. }, "线程2").start();
  55. new Thread(() -> {
  56. for (int i = 0; i < 10; i++) {
  57. try {
  58. share.incr();
  59. } catch (InterruptedException e) {
  60. e.printStackTrace();
  61. }
  62. }
  63. }, "线程3").start();
  64. new Thread(() -> {
  65. for (int i = 0; i < 10; i++) {
  66. try {
  67. share.decr();
  68. } catch (InterruptedException e) {
  69. e.printStackTrace();
  70. }
  71. }
  72. }, "线程4").start();
  73. }
  74. }