线程同步的一些思考

这篇具有很好参考价值的文章主要介绍了线程同步的一些思考。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

线程同步的一些思考

A、B轮流

这种没有顺序依赖的打印场景,只需要将notify唤醒提前,就不会有死锁问题

public class PrintUtile {

  private static final Object lock = new Object();

  public static void main(String[] args) throws InterruptedException {
    Thread threadA = new Thread(new PrintA());
    Thread threadB = new Thread(new PrintB());

//    extractedA(threadA, threadB);
    extractedB(threadA, threadB);
  }

  private static void extractedA(Thread threadA, Thread threadB) throws InterruptedException {
    threadA.start();
    Thread.sleep(1000);
    threadB.start();
  }
  private static void extractedB(Thread threadA, Thread threadB) throws InterruptedException {
    threadB.start();
    Thread.sleep(1000);
    threadA.start();
  }

  static class PrintA implements Runnable {

    @Override
    public void run() {
      for (int i = 0; i < 10; i++) {
        synchronized (lock) {
            System.out.println("A");
            lock.notify();
          try {
            lock.wait();
          } catch (InterruptedException e) {
            e.printStackTrace();
          }
        }
      }
    }
  }

  static class PrintB implements Runnable {

    @Override
    public void run() {
      for (int i = 0; i < 10; i++) {
        synchronized (lock) {
          System.out.println("B");
          lock.notify();
          try {
            lock.wait();
          } catch (InterruptedException e) {
            e.printStackTrace();
          }
        }
      }
    }
  }
}

先A后B

正确写法:

class PrintUtile {

  private static final Object lock = new Object();
  private static boolean isPrintA = false;

  public static void main(String[] args) throws InterruptedException {
    Thread threadA = new Thread(new PrintA());
    Thread threadB = new Thread(new PrintB());

//    extractedA(threadA, threadB);
    extractedB(threadA, threadB);
  }

  private static void extractedA(Thread threadA, Thread threadB) throws InterruptedException {
    threadA.start();
    Thread.sleep(1000);
    threadB.start();
  }
  private static void extractedB(Thread threadA, Thread threadB) throws InterruptedException {
    threadB.start();
    Thread.sleep(1000);
    threadA.start();
  }

  static class PrintA implements Runnable {

    @Override
    public void run() {
      for (int i = 0; i < 10; i++) {
        synchronized (lock) {
          if (!isPrintA) {
            System.out.println("A");
            isPrintA = true;
            lock.notify();
          }
          try {
            lock.wait();
          } catch (InterruptedException e) {
            e.printStackTrace();
          }
        }
      }
    }
  }

  static class PrintB implements Runnable {

    @Override
    public void run() {
      for (int i = 0; i < 10; i++) {
        synchronized (lock) {
          if (!isPrintA) {
            try {
              lock.wait();
            } catch (InterruptedException e) {
              e.printStackTrace();
            }
          }
          System.out.println("B");
          isPrintA = false;
          lock.notify();
        }
      }
    }
  }
}

总结:
说一下这种场景的特点,就是有顺序,那么意味着需要标识。意味着其它n个线程执行只有其中一个满足条件的线程能够往下执行然后通知,这个很重要,因为线程抢夺资源我们通常不会进行控制,也就是意味着线程刚开始的执行顺序我们是无法控制的。那么也就意味着在其他n-1条线程先执行的情况下,其他线程肯定都会阻塞,也就是说会wait()。那么这里就有一个编码干货,就是目标第一个执行的线程必须先通知然后再阻塞,也就是先notify()再wait()。

误区:之前写的时候会出现这么一种错误,造成了死锁。
写的思路是这样的

  1. 线程A先进行打印,然后wait,在notify
  2. 线程B在打印,然后notify
    这种思路在线程A先拿到CPU资源的情况下没有问题,但是如果是线程B先拿到CPU资源的话就会导致线程B先wait阻塞了,然后线程A执行打印了,但是先执行了wait,导致A、B同时阻塞,没有其它线程进行通知,造成死锁的情况。

思考,就是A肯定是第一个要执行关键代码逻辑的线程,而其它线程可能都会先行阻塞,所以既然A是第一个会执行关键逻辑代码的线程,那么执行完毕后A虽然也需要阻塞waite,但是在阻塞之前要先通知notify及时的唤醒其它线程才行。文章来源地址https://www.toymoban.com/news/detail-528184.html

  static class PrintA implements Runnable {

    @Override
    public void run() {
      for (int i = 0; i < 10; i++) {
        synchronized (lock) {
          if (!isPrintA) {
            System.out.println("A");
            isPrintA = true;
            try {
              lock.wait();
            } catch (InterruptedException e) {
              e.printStackTrace();
            }
          }
          lock.notify();
        }
      }
    }
  }

  static class PrintB implements Runnable {

    @Override
    public void run() {
      for (int i = 0; i < 10; i++) {
        synchronized (lock) {
          if (!isPrintA) {
            try {
              lock.wait();
            } catch (InterruptedException e) {
              e.printStackTrace();
            }
          }
          System.out.println("B");
          isPrintA = false;
          lock.notify();
        }
      }
    }
  }

到了这里,关于线程同步的一些思考的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【Java基础】线程同步类 CountDownLatch

    ​ 关于作者:CSDN内容合伙人、技术专家, 从零开始做日活千万级APP。 专注于分享各领域原创系列文章 ,擅长java后端、移动开发、人工智能等,希望大家多多支持。 正好今天项目中用到了CountDownLatch,那我们正好总结一下,通过本文你可以学到什么是CountDownLatch及其原理,

    2024年02月12日
    浏览(38)
  • java多线程怎么同步返回结果

    在 Java 多线程中,如果需要等待线程执行完成并返回结果,可以使用 Java 的线程同步机制来实现。以下是一些常用的方式: 使用 join() 方法:可以使用线程的 join() 方法来等待线程执行完成。在主线程中调用 join() 方法,会阻塞主线程,直到该线程执行完成。在被等待的线程执

    2024年02月14日
    浏览(22)
  • Java多线程系列——同步关键字

    目录 一、线程安全和数据不一致性 二、synchronized的作用 三、synchronized工作原理 四、锁的级别 五、synchronized的优点与缺点 六、实战应用 七、总结 在Java中, synchronized 是并发编程中的一个基本构建块,用于控制多个线程对共享资源的访问,以确保数据的一致性

    2024年02月21日
    浏览(32)
  • Java线程同步和协作的5种方式

    有3个线程为A,B,C,同时启动,C必须等待A和B完成才能继续执行,如何实现? 要求:仅使用 java 语言和它原生API 使用 Java 中提供的 CountDownLatch 类实现线程之间的同步和协作 使用 Java 中提供的 CyclicBarrier 类实现线程之间的同步和协作 使用join()方法:Thread类提供了join()方法,

    2024年02月02日
    浏览(64)
  • 学Java线程,你不知道什么是AQS?一文带你了解Java多线程同步的灵魂

    关于作者:CSDN内容合伙人、技术专家, 从零开始做日活千万级APP。 专注于分享各领域原创系列文章 ,擅长java后端、移动开发、人工智能等,希望大家多多支持。 我们继续总结学习 Java基础知识 ,温故知新。 CLH(Craig, Landin, and Hagersten locks)是一种自旋锁,能确保无饥饿性,提

    2024年02月16日
    浏览(32)
  • Java并发编程(三)线程同步 上[synchronized/volatile]

    当使用多个线程来访问同一个数据时,将会导致数据不准确,相互之间产生冲突,非常容易出现线程安全问题,比如多个线程都在操作同一数据,都打算修改商品库存,这样就会导致数据不一致的问题。 所以我们通过线程同步机制来保证线程安全,加入同步锁以避免在该线程没有完成

    2024年02月13日
    浏览(30)
  • 学Java线程,你不知道什么是AQS?一文带你进入Java多线程同步的灵魂-AbstractQueuedSynchronizer

    关于作者:CSDN内容合伙人、技术专家, 从零开始做日活千万级APP。 专注于分享各领域原创系列文章 ,擅长java后端、移动开发、人工智能等,希望大家多多支持。 我们继续总结学习 Java基础知识 ,温故知新。 CLH(Craig, Landin, and Hagersten locks)是一种自旋锁,能确保无饥饿性,提

    2024年02月16日
    浏览(25)
  • Java多线程:读写锁和两种同步方式的对比

    读写锁ReentrantReadWriteLock概述 大型网站中很重要的一块内容就是数据的读写,ReentrantLock虽然具有完全互斥排他的效果(即同一时间只有一个线程正在执行lock后面的任务),但是效率非常低。所以在JDK中提供了一种读写锁ReentrantReadWriteLock,使用它可以加快运行效率。 读写锁表

    2023年04月09日
    浏览(29)
  • 【Java练习题汇总】《第一行代码JAVA》多线程篇,汇总Java练习题——线程及多线程概念、Thread 类及 Runnable 接口、线程状态、synchronized同步操作...

    一、填空题 Java 多线程可以依靠________ 、________ 和________ 三种方式实现。 多个线程操作同一资源的时候需要注意________,依靠________ 实现,实现手段是:________ 和________,过多的使用,则会出现________ 问题。 Java 程序运行时,至少启动________ 个线程,分别是________ 和_

    2024年02月16日
    浏览(41)
  • 【Java多线程】关于多线程的一些案例 —— 单例模式中的饿汉模式和懒汉模式以及阻塞队列

    目录 1、单例模式 1.1、饿汉模式 2.1、懒汉模式  2、阻塞队列 2.1、BlockingQueue 阻塞队列数据结构 对框架和设计模式的简单理解就是,这两者都是“大佬”设计出来的,让即使是一个代码写的不太好的“菜鸡程序员”也能写出还可以的代码。 设计模式也可以认为是对编程语言语

    2024年03月23日
    浏览(82)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包