JUC详解(各种乱七八糟的锁)

本文详细介绍了Java并发编程中的JUC(Java Util Concurrency)库,包括Lock锁、并发集合(如CopyOnWriteArrayList、ConcurrentHashMap)、线程计数器(CyclicBarrier、CountDownLatch)、线程池(ThreadPoolExecutor)以及并发问题解决方案,如死锁排查。还探讨了Volatile的可见性、非原子性以及避免指令重排,以及CAS和ABA问题。
摘要由CSDN通过智能技术生成

1JUC

在这里插入图片描述

2回顾多线程知识

进程和线程:
进程:一个进程可以包含多个线程,至少是一个线程,java默认2个线程——main、GC(垃圾回收)
线程:开了一个软件,写字的时候也会有自动保存的线程在进行,ThreadRunnableCallable
java开启不了线程,java操作的是底层的C++,java无法操作,用的是虚拟机
并发与并行:
并发:多线程操作同一个资源(假设cpu只有一核的时候,模拟多线程,快速交替处理线程)
并行:CPU多核情况下才有,多个线程同时执行

并发编程的本质:充分利用电脑的CPU
线程有几种状态:6种:new(创建)、runnable(运行)、blocked(阻塞)、wait(等待)、timed_waiting(超时等待)
terminated(终止)

wait与sleep的区别:
1.来自不同的类——wait(Object)、sleep(Thread2.关于锁——wait会释放锁,而sleep不会释放
3.适用范围不一样——wait必须在同步代码块中执行,sleep则不用
4.w捕获异常——wait不需要捕获异常、sleep需要捕获异常

3Lock锁(重点)

传统Synchronized解决有顺序卖票问题

package JUC;
/*基本的卖票的例子
线程是一个单独的资源类
* */
public class Demo02SaleTicket {
   
    public static void main(String[] args) {
   
        Ticket ticket = new Ticket();

        new Thread(()->{
   
            for (int i = 0; i < 60; i++) {
   
                ticket.sale();
            }

        },"A").start();
        new Thread(()->{
   
            for (int i = 0; i < 60; i++) {
   
                ticket.sale();
            }

        },"B").start();
        new Thread(()->{
   
            for (int i = 0; i < 60; i++) {
   
                ticket.sale();
            }
        },"C").start();
    }
}

class Ticket{
   
    private int num=30;
    public synchronized void sale(){
   
        if (num>0){
   
            System.out.println(Thread.currentThread().getName()+"卖出了第"+(num--)+"票,剩余"+num);
        }
    }
}

4Lock锁

package JUC;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class Demo03Lock {
   
    public static void main(String[] args) {
   
        Ticket1 ticket1 = new Ticket1();

    }
}

//Lock锁————三步骤——1.new ReentrantLock 2.加锁 3.解锁
class Ticket1{
   
    private int num=30;
    //ReentrantLock---java默认非公平锁,也就是默认可以插队(比较合理,3秒的不需要等待3小时的线程)
    Lock lock=new ReentrantLock();
    public void sale(){
   
        lock.lock();//加锁
        try {
   
            //业务代码
            if (num>0){
   
                System.out.println(Thread.currentThread().getName()+"卖出了第"+(num--)+"票,剩余"+num);
            }
        } catch (Exception e) {
   
            e.printStackTrace();
        }finally {
   
            lock.unlock();//解锁
        }


    }

}

5JUC版的生产者与消费者问题(虚假唤醒)

package JUC;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/*JUC版的生产者与消费者问题
通过Lock可以找到Condition
以下的是无序的随机的状态结果,JUC的优势还没有体现出来
ReentrantLock是可重入的意思
* */
public class Demo05JUC1 {
   
    public static void main(String[] args) {
   
        Date1 date1 = new Date1();

        new Thread(()->{
   for (int i = 0; i < 10; i++) {
   
            try {
   
                date1.increment();
            } catch (InterruptedException e) {
   
                e.printStackTrace();
            }
        }
        },"A").start();
        new Thread(()->{
   for (int i = 0; i < 10; i++) {
   
            try {
   
                date1.decrement();
            } catch (InterruptedException e) {
   
                e.printStackTrace();
            }
        }
        },"B").start();
        new Thread(()->{
   for (int i = 0; i < 10; i++) {
   
            try {
   
                date1.increment();
            } catch (InterruptedException e) {
   
                e.printStackTrace();
            }
        }
        },"C").start();
        new Thread(()->{
   for (int i = 0; i < 10; i++) {
   
            try {
   
                date1.decrement();
            } catch (InterruptedException e) {
   
                e.printStackTrace();
            }
        }
        },"D").start();
    }


}
class Date1{
   
    private int num=0;
    Lock lock=new ReentrantLock();
    Condition condition = lock.newCondition();


    public  void increment() throws InterruptedException {
   
        lock.lock();
        try {
   
            while (num!=0){
   
                //等待
                //this.wait();JUC之前普通的
                condition.await();
            }
                num++;
                System.out.println(Thread.currentThread().getName()+"=="+num);
                //通知线程B,我+1完毕了this.notifyAll();JUC之前普通的
                condition.signalAll();//唤醒全部

        } catch (InterruptedException e) {
   
            e.printStackTrace();
        } finally {
   
            lock.unlock();
        }

    }


    public  void decrement() throws InterruptedException {
   
        lock.lock();
        try {
   
            while (num==0){
   
                //等待
                //this.wait();
                condition.await();
            }
            num--;
            System.out.println(Thread.currentThread().getName()+"=="+num);
            //通知线程B,我-1完毕了 JUC之前的this.notifyAll();
            condition.signalAll();//唤醒全部
        } catch (InterruptedException e) {
   
            e.printStackTrace();
        } finally {
   
            lock.unlock();
        }
    }
}

6有序线程

package JUC;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/*实现生产者与消费者的有序JUC执行
三条线程按照循环顺序执行
* */
public class Demo06JUC2 {
   
    public static void main(String[] args) {
   
        new Thread(()->{
   },"A").start();
        new Thread(()->{
   },"B").start();
        new Thread(()->{
   },"C").start();

    }
}

//资源类
class Date3{
   
    private Lock lock=new ReentrantLock();
    private Condition condition = lock.newCondition();
    private Condition condition2 = lock.newCondition();
    private Condition condition3 = lock.newCondition();
    private int num=1;

    public void print1(){
   
        lock.lock();
        try {
   //业务代码,判断-执行-通知
        if (num!=1){
   
            condition.await();
        }
        System.out.println(Thread.currentThread().getName()+"1111");
        //通知唤醒
            num=2;
            condition2.signal();
        } catch (Exception e) {
   
            e.printStackTrace();
        } finally {
   
            lock.unlock();
        }
    }
    public void print2(){
   
        lock.lock();
        try {
   
            if (num!=2){
   
                condition2.await();
            }
            System.out.println(Thread.currentThread().getName()+"2222");
            num=3;
            condition3.signal();
        } catch (Exception e) {
   
            e.printStackTrace();
        } finally {
   
            lock.unlock();
        }
    }
    public void print3(){
   
        lock.lock();
        try {
   
            if (num!=3){
   
                condition3.await();
            }
            System.out.println(Thread.currentThread().getName()+"3333");

            num=1;
            condition.signal();
        } catch (Exception e) {
   
            e.printStackTrace();
        } finally {
   
            lock.unlock();
        }
    }
}

7八锁问题

package JUC;

import java.util.concurrent.TimeUnit;

/*什么是锁,锁的对象是谁——查看自己的收藏笔记
8锁,就是关于锁的8个问题
1.标准情况下,线程先执行哪个?————先发短信再打电话(原因:锁的存在)
2.发短信延迟4秒的情况下————还是先短信再电话,先执行发短信,因为有同步锁
3.增加了一个普通方法后,是执行发短信还是hello,限制性普通方法,普通方法不受锁的限制
4.两个对象的情况下,先执行发短信还是打电话——————打电话,因为两把锁不一样,打电话的锁有延迟
5.静态方法的时候,两个线程先执行哪个?——————加了static以后锁的就是class对象,类的模板只有一个所以和原先锁的是对象没有关系

* */
public class Demo07suo1 {
   
    public static void main(String[] args) {
   
        Phone phone = new Phone();
        Phone phone1 = new Phone();
        //第一条线程
        new Thread(()->{
   
            phone.send();
        },"A").start(
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值