1 JUC简介

JUC就是java.util.concurrent的简称,这是一个处理线程的工具包,JDK1.5开始出现的。

进程和线程、管程

进程:系统资源分配的基本单位;它是程序的一次动态执行过程。系统运行一个程序即是一个进程从创建,运行到消亡的过程。

线程:系统资源调度的基本单位;它是一个比进程更小的执行单位。一个进程在执行过程中可以产生多个线程。同类的多个线程共享进程的堆和方法区资源,但是每个线程有自己的程序计数器、虚拟机栈和本地方法栈,所以系统在产生一个线程,或是在各个线程之间作切换工作时,负担要比进程小得多,也正因为如此,线程也被称为轻量级进程

协程:一种比线程更加轻量级的存在。协程完全由程序所控制(在用户态执行),带来的好处是性能大幅度的提升。一个操作系统中可以有多个进程;一个进程可以有多个线程;同理,一个线程可以有多个协程。由于协程切换是在线程内完成的,所以涉及到的资源比较少,几乎只是切换了寄存器和协程栈的内容。

管程:共享资源访问模型

管程在操作系统中被称为Monitor对象,也就是Java中的锁

管程是一种同步机制,用于管理共享资源的访问过程,保证某个时刻只允许一个线程访问资源

jvm同步就是基于进入退出临界区的时候使用管程对象来实现的,管程对象随着对象的创建而创建,随着对象的消亡而消亡

线程的状态
  1. NEW:创建
  2. RUNNABLE:运行
  3. BLOCKED:阻塞
  4. WAITING:等待
  5. TIMED_WAITING:等待(超时不再等待)
  6. TERMINATED:终结
public enum State {
/**
* Thread state for a thread which has not yet started.
*/
NEW, /**
* Thread state for a runnable thread. A thread in the runnable
* state is executing in the Java virtual machine but it may
* be waiting for other resources from the operating system
* such as processor.
*/
RUNNABLE, /**
* Thread state for a thread blocked waiting for a monitor lock.
* A thread in the blocked state is waiting for a monitor lock
* to enter a synchronized block/method or
* reenter a synchronized block/method after calling
* {@link Object#wait() Object.wait}.
*/
BLOCKED, /**
* Thread state for a waiting thread.
* A thread is in the waiting state due to calling one of the
* following methods:
* <ul>
* <li>{@link Object#wait() Object.wait} with no timeout</li>
* <li>{@link #join() Thread.join} with no timeout</li>
* <li>{@link LockSupport#park() LockSupport.park}</li>
* </ul>
*
* <p>A thread in the waiting state is waiting for another thread to
* perform a particular action.
*
* For example, a thread that has called {@code Object.wait()}
* on an object is waiting for another thread to call
* {@code Object.notify()} or {@code Object.notifyAll()} on
* that object. A thread that has called {@code Thread.join()}
* is waiting for a specified thread to terminate.
*/
WAITING, /**
* Thread state for a waiting thread with a specified waiting time.
* A thread is in the timed waiting state due to calling one of
* the following methods with a specified positive waiting time:
* <ul>
* <li>{@link #sleep Thread.sleep}</li>
* <li>{@link Object#wait(long) Object.wait} with timeout</li>
* <li>{@link #join(long) Thread.join} with timeout</li>
* <li>{@link LockSupport#parkNanos LockSupport.parkNanos}</li>
* <li>{@link LockSupport#parkUntil LockSupport.parkUntil}</li>
* </ul>
*/
TIMED_WAITING, /**
* Thread state for a terminated thread.
* The thread has completed execution.
*/
TERMINATED;
}
wait & sleep
  • wait:释放掉当前线程持有的锁,使当前线程进入一个等待队列处于等待状态(WAITING),直到其他线程调用此对象的notify()或notifyAll()方法唤醒线程。wait(long timeout)则是在指定时间内被其他线程唤醒,超过时间自动被唤醒。
  • 强制当前正在执行的线程休眠(暂停执行),在苏醒之前不会返回到可运行状态,当睡眠时间到期,则返回到可运行状态。

区别

  1. sleep是Thread的静态方法,而wait是Object中的方法,任何对象实例都能够调用。
  2. sleep不需要占用锁也不会释放锁,而wait会释放锁,所以调用的前提是当前线程占有锁(即代码处于synchronized代码块中)
  3. 它们都会被interrupted方法中断。
并发与并行
  • 并发:所有任务按照一定的顺序执行,只有前面的任务执行完成后面的任务才能执行
  • 并行:同时可以运行多个任务,单核处理器实际上是宏观上并行微观上串行
用户线程和守护线程
  • 用户线程:一般自定义的线程都属于自定义线程
  • 守护线程:运行在后台的线程,如:垃圾回收线程,如果只剩下守护线程,则主线程结束守护线程也会结束
public static void main(String[] args) {
var thread = new Thread(() -> {
System.out.println(Thread.currentThread().getName() + "::" + Thread.currentThread().isDaemon());
while(true) { }
});
thread.start(); System.out.println(Thread.currentThread().getName() + " over");
}

main over

Thread-0::false

且用户线程一直在运行,JVM不会结束

public class Main {
public static void main(String[] args) {
var thread = new Thread(() -> {
System.out.println(Thread.currentThread().getName() + "::" + Thread.currentThread().isDaemon());
while(true) { }
});
thread.setDaemon(true);
thread.start(); System.out.println(Thread.currentThread().getName() + " over");
}
}

main over

主线程结束,守护线程也结束(还没来得及运行),JVM也结束了

2 Synchronized

Synchronized是一种同步的可重入锁,可以修饰的对象有下面几种:

  1. 代码块,被修饰的代码块称作同步代码块

  2. 方法,被修饰的方法称作是同步方法作用范围是整个方法,作用的对象是调用这个方法的对象

    Synchronized不属于方法定义的一部分,因此不能被继承,子类不声明的话默认不是同步的

  3. 静态方法,作用范围是整个静态方法,作用对象是这个类的所有实例对象

  4. 一个类,作用范围是整个括号的部分,作用对象是这个类的所有实例对象

举例:售票员买票

分析:

​ 资源类:票,属性:30张,操作方法:卖

public class TicketSale {
public static void main(String[] args) {
Ticket ticket = new Ticket(3000);
Runnable r = () -> {
while(ticket.getNum() > 0) {
ticket.sale();
}
};
new Thread(r, "A").start();
new Thread(r, "B").start();
new Thread(r, "C").start();
}
} class Ticket {
private int num;
public Ticket(int num) {
this.num = num;
}
@Override
public String toString() {
return String.valueOf(this.num);
} public synchronized void sale() {
if(this.num > 0) {
System.out.println(Thread.currentThread().getName() +
" sale 1 ticket, there are " + --num + " tickets left" );
}
} public int getNum() {
return this.num;
} }

3 Lock接口

package java.util.concurrent.locks:为锁和等待条件提供的一个框架的接口和类,不同于内置同步和监视器。

可重入锁:可以重复使用的锁,即某个线程已经获得了某个锁,再次获取锁而不会出现死锁,可重入锁有:

  • synchronized
  • ReentrantLock:ReentrantLock 和 synchronized 不一样,需要手动释放锁,所以使用 ReentrantLock的时候一定要手动释放锁,并且加锁次数和释放次数要一样
class LTicket {
private int num = 30;
private final ReentrantLock lock;
LTicket() {
lock = new ReentrantLock();
}
public void sale() {
lock.lock();
try {
if(this.num > 0) {
System.out.println(Thread.currentThread().getName() +
" sale 1 ticket, there are " + --num + " tickets left" );
}
} finally {
lock.unlock();
}
}
} public class TicketSale {
public static void main(String[] args) {
LTicket ticket = new LTicket();
Runnable r = () -> {
for(int i = 0; i < 40; i++) {
ticket.sale();
}
};
new Thread(r, "A").start();
new Thread(r, "B").start();
new Thread(r, "C").start();
}
}

4 lock和synchronized的区别

  1. Lock是一个接口,synchronized是java语言关键字,是内置语言实现
  2. synchronized中发生异常,会自动释放占有的锁,而lock接口实现类需要手动释放,否则可能会导致死锁
  3. lock可以让等待的线程响应中断,而synchronized不会,等待的线程会一直等待下去
  4. 通过lock可以知道有没有获取成功锁,synchronized不行
  5. lock可以提高多个线程读的效率
  6. 资源竞争激烈的时候,lock的性能远远优于synchronized

JUC(一)JUC简介与Synchronized和Lock的更多相关文章

  1. JUC 并发编程--07 阻塞队列版本的 生产者消费者(不使用synchronized和 lock),也有一些疑惑,最终解惑

    直接上代码: 前提是你已经 熟悉了原子类,volatile,和阻塞队列 public class JucPCdemo03 { /** * 阻塞队列的应用: 这里实现的生产者消费者,生产一个消费一个 * ...

  2. 第44天学习打卡(JUC 线程和进程 并发和并行 Lock锁 生产者和消费者问题 如何判断锁(8锁问题) 集合类不安全)

    什么是JUC 1.java.util工具包 包 分类 业务:普通的线程代码 Thread Runnable 没有返回值.效率相比Callable相对较低 2.线程和进程 进程:一个程序.QQ.exe, ...

  3. 用阻塞队列实现一个生产者消费者模型?synchronized和lock有什么区别?

    多线程当中的阻塞队列 主要实现类有 ArrayBlockingQueue是一个基于数组结构的有界阻塞队列,此队列按FIFO原则对元素进行排序 LinkedBlockingQueue是一个基于链表结构的 ...

  4. java多线程(3)---synchronized、Lock

    synchronized.Lock 一.概述 1.出现线程不安全的原因是什么? 如果我们创建的多个线程,存在着共享数据,那么就有可能出现线程的安全问题:当其中一个线程操作共享数据时,还未操作完成,另外 ...

  5. 线程安全、数据同步之 synchronized 与 Lock

    本文Demo下载传送门 写在前面 本篇文章讲的东西都是Android开源网络框架NoHttp的核心点,当然线程.多线程.数据安全这是Java中就有的,为了运行快我们用一个Java项目来讲解. 为什么要 ...

  6. 【转载】synchronized 与 Lock 的那点事

    最近在做一个监控系统,该系统主要包括对数据实时分析和存储两个部分,由于并发量比较高,所以不可避免的使用到了一些并发的知识.为了实现这些要求,后台使用一个队列作为缓存,对于请求只管往缓存里写数据.同时启 ...

  7. 转:synchronized和LOCK的实现原理---深入JVM锁机制

    JVM底层又是如何实现synchronized的? 目前在Java中存在两种锁机制:synchronized和Lock,Lock接口及其实现类是JDK5增加的内容,其作者是大名鼎鼎的并发专家Doug ...

  8. synchronized 与 Lock 的那点事

    最近在做一个监控系统,该系统主要包括对数据实时分析和存储两个部分,由于并发量比较高,所以不可避免的使用到了一些并发的知识.为了实现这些要求,后台使用一个队列作为缓存,对于请求只管往缓存里写数据.同时启 ...

  9. JAVA中synchronized和lock详解

         目前在Java中存在两种锁机制:synchronized和Lock,Lock接口及其实现类是JDK5增加的内容,其作者是大名鼎鼎的并发专家Doug Lea.本文并不比较synchronize ...

  10. Java多线程编程(四)—浅谈synchronized与lock

    一.共享资源竞争问题 在Java语言的并发编程中,由于我们不知道线程实际上在何时运行,所以在实际多线程编程中,如果两个线程访问相同的资源,那么由于线程运行的不确定性便会在这种多线程中产生访问错误.所以 ...

随机推荐

  1. C语言初级阶段8——预处理

    C语言初级阶段8--预处理 预定义符号 1.概念:预处理是编译之前做的一些事. 2.常用的预定义符号: 注意:: (1)-(4)的格式占位符都用%是,如:printf("%s",D ...

  2. vue + vant 移动端适配

    1. 设置动态根字号大小,/public/phone-adapt.js,在index.html中引入 (function (doc, win) { const docEl = win.document ...

  3. windows11中使用ctypes运行时出错:AttributeError: function *** not found

    最近我在研究用ctypes实现python调用c,按照晚上的教程写下了类似下面的c程序: #include <stdio.h> int nn_test(int num){ printf(& ...

  4. VBA类模块完全教程(www.accessoft.com软件网)

    这份礼物送给现在想学习类知识或曾经学过但因为各种原因没有"修成正果"的朋友,我期望的结果是这篇文章后,您可以在类模块中像在标准模块中写代码一样熟练,我也期望不至于太乏味而使您没有耐 ...

  5. Ubuntu 22.04 安装 VMWare 16.2.3 后无法启动

    异常日志: 2022-06-13T03:49:56.019Z In(05) host-29676 In file included from /tmp/modconfig-XR2GVI/vmmon-o ...

  6. git merge的原理

    当我我们拉去代码合并到master的另一个分支上面去的时候 只是对比当前分支commit的修改与增加的代码,其他代码以master为主.

  7. thread互斥测试

    thread互斥测试 实践代码 #include <stdio.h> #include <stdlib.h> #include <pthread.h> //linu ...

  8. dotNetCore创建Windows服务程序并安装服务

    一.创建控制台程序 二.在项目中添加新建项,选择Windows服务类型. 此时会出现一个错误提示,这是因为尚未添加windows服务控制引用造成的. 三.添加Nuget包,System.Service ...

  9. LaTeX in 24 Hours - 2. Fonts Selection

    文章目录 本章内容:字体 2.1 Text-Mode Fonts 2.2 Math-Mode Fonts 2.3 Emphasized Fonts 2.4 Colored Fonts 其他章节目录: ...

  10. adb 全局

    win10: 我的电脑-右键属性--系统保护--高级--环境变量--选择path--编辑--点击新建 在新建条目下输入 C:\Users\GL\platform-tool--重新打开cmd 测试adb ...