• 并发编程专题


    串行和并行:
          串行:一个线程在处理操作
          并行:多个线程在处理同一个操作
    什么叫做并发编程:在多线程环境下,应用程序的执行
    并发编程的目的:充分运用到资源,提高程序的效率
    什么情况下用到并发编程:
          1.在线程阻塞时,导致应用程序停止
          2.处理任务时间过长时,可以创建子任务,来进行分段处理
          3.间断任务执行


    一.并发编程中待解决的问题
    1.并发编程中频繁上下文切换的问题
           频繁上下文切换,可能会带来一定的性能开销
    如何减少上下文性能开销:
          1.无锁并发编程
          2.CAS
          3.使用最少线程数量
          4.协程:在单线程环境下进行多任务的调度,可以在多任务之间进行任务切换


    2.并发编程中死锁问题
           多个线程在抢占资源,但是抢占过程当中资源如果被占用,会造成阻塞,如果多个线程互抢资源时,就会造成死锁情况,死锁会导致应用程序的阻塞

    案例: 

            

    public class DeadLockDemo {
    //资源
    private static final Object HAIR_A=new Object();
    private static final Object HAIR_B=new Object();
    
    public static void main(String[] args) {
    //第一个人
    new Thread(()->{
    //护住自己的头发
    synchronized (HAIR_A){
    System.out.println("第一个人护住自己的头发,准备薅第二个人的头发");
    //延迟时间
    try {
    Thread.sleep(100);
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    //薅第二个人的头发
    synchronized (HAIR_B){
    System.out.println("第一个人薅到了第二个人的头发");
    }
    }
    }).start();
    
    
    //第二个人
    new Thread(()->{
    //护住自己的头发
    synchronized (HAIR_B){
    System.out.println("第二个人护住自己的头发,准备薅第一个人的头发");
    //延迟时间
    try {
    Thread.sleep(100); //当前线程休眠,让渡CPU资源
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    //薅第一个人的头发
    synchronized (HAIR_A){
    System.out.println("第二个人薅到了第一个人的头发");
    }
    }
    }).start();
    }
    }

    如何预防死锁问题:
           1.破坏请求和保持条件:在申请资源时,一次性将资源都申请到
           2.破坏不可占用条件:抢占资源如何不满足,那就释放所有资源,以后如果再需要则再次申请即可
           3.破坏循环等待条件

    3.线程安全问题
          多个线程同时操作同一个资源,可能会造成资源数据不安全问题

    示例:

           

    public class UnsafeThread {
    //资源
    private static int num=0;
    //计算线程数量
    private static CountDownLatch countDownLatch=new CountDownLatch(10);
    //对资源进行操作
    public static void inCreate(){
    num++;
    }
    
    
    public static void main(String[] args) throws InterruptedException {
    for (int i = 0 ; i < 10 ; i++ ){
    new Thread(()->{
    for (int j = 0 ; j < 100; j++){
    inCreate();
    try {
    Thread.sleep(100);
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    }
    //每一个线程执行完毕,让计数-1
    countDownLatch.countDown();
    }).start();
    }
    //等待计数器为0或者小于0执行await下面代码
    countDownLatch.await();
    System.out.println(num);
    }
    }


    解决线程不安全问题:

        

    public class UnsafeThread {
    //资源
    private static int num=0;
    //计算线程数量
    private static CountDownLatch countDownLatch=new CountDownLatch(10);
    private static ReentrantLock reentrantLock = new ReentrantLock();
    
    //对资源进行操作
    public static void inCreate(){
    
    //上锁
    reentrantLock.lock();
    num++;
    reentrantLock.unlock();
    
    
    }
    
    public static synchronized void inCreate(){
    
    //上锁
    
    num++;
    
    }
    
    public static synchronized void inCreate(){
    //上锁
    synchronized(UnsafeThread.class){
    num++;
    }
    }
    
    
    public static void main(String[] args) throws InterruptedException {
    for (int i = 0 ; i < 10 ; i++ ){
    new Thread(()->{
    for (int j = 0 ; j < 100; j++){
    inCreate();
    try {
    Thread.sleep(100);
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    }
    //每一个线程执行完毕,让计数-1
    countDownLatch.countDown();
    }).start();
    
    }
    //等待计数器为0或者小于0执行await下面代码
    countDownLatch.await();
    //获取到当前计数器中的线程数量
    /*while (true){
    if(countDownLatch.getCount()<=5){
    System.out.println(num);
    break;
    }
    }*/
    System.out.println(num);
    
    
    }
    }
  • 相关阅读:
    opencv图片右转函数
    多项式相加实验代码和报告
    C++下实现同接口下多个类作为参数的调用和传参
    Betsy Ross Problem
    matlab绘制实用日历实例代码
    node-sass 安装卡在 node scripts/install.js 解决办法
    如何管理自己?
    Webstorm 11 注册/破解方法
    解决play-1.4.0在linux或mac下提示No such file or directory的问题
    PlayFramework 1.2.x 在Controller 中识别JSON提交
  • 原文地址:https://www.cnblogs.com/liuying23/p/12519747.html
Copyright © 2020-2023  润新知