juc

java并发变成及juc包的应用

╄→尐↘猪︶ㄣ 提交于 2020-01-28 03:51:22
多线程: windows操作系统是多任务操作系统,它以进程为单位,一个进程是一个包含有自身地址的程序,每个正在独立执行的程序都称为进程,进程是系统进行资源分配和调用的独立单位,每个进程有自己的内存空间和系统资源。系统可以分配给每个进程一段有限的使用CPU时间,CPU在这个时间片中执行某个进程,然后下一个时间片又跳到另一个进程中去执行,由于CPU转换较快,所以使的每个进程好像同时进行,多核CPU的多核同时运行,但是进程数远远大于核数,所以还是要依靠切换进程来做。一个线程则是进程中的执行流程,一个进程中可以同时包括多个线程,每个线程也可以得到一小段程序的执行时间,这样一个进程就可以具有多个并发执行的线程,在单线程中,程序的代码按照调用顺序依次往下执行,如果需要一个进程同时完成多段代码的操作,就需要产生多线程(多条执行路径)。多线程可以提高应用程序的使用率,为了有更高的几率抢到CPU的执行权,但我们不能保证哪一个线程能够在哪一个时刻抢到,所以线程的执行有随机性。在并发编程中,我们通常会遇到以下三个问题:原子性问题,可见性问题,有序性问题。 线程的两种调度模型:平均分配每个线程占用CPU的时间片,上面说的就是这种,第二种就是抢占式调度模型:优先让优先级高的线程使用CPU,如果线程的优先级相同,会随机选一个,优先级高仅仅表示线程获取的cpu时间片的几率相对对多些

【JUC】JDK1.8源码分析之ReentrantReadWriteLock

喜欢而已 提交于 2020-01-25 22:14:52
重入锁 ReentrantLock是排他锁 ,排他锁在同一时刻仅有一个线程可以进行访问,但是在大多数场景下,大部分时间都是提供读服务,而写服务占有的时间较少。然而读服务不存在数据竞争问题,如果 一个线程在读时禁止其他线程读势必会导致性能降低 。所以就提供了读写锁。 读写锁维护着一对锁,一个读锁和一个写锁,读锁是共享锁,写锁是独占锁 。通过分离读锁和写锁,使得 并发性比一般的排他锁有了较大的提升 :在同一时间可以允许多个读线程同时访问,但是在写线程访问时,所有读线程和写线程都会被阻塞。 读写锁的主要特性: 公平性:支持公平性和非公平性。 重入性:支持重入。读写锁最多支持65535个递归写入锁和65535个递归读取锁。 锁降级:遵循获取写锁、获取读锁在释放写锁的次序,写锁能够降级成为读锁 读写锁ReentrantReadWriteLock实现接口ReadWriteLock,该接口维护了一对相关的锁,一个用于只读操作,另一个用于写入操作。只要没有 writer,读取锁可以由多个 reader 线程同时保持。写入锁是独占的。 public interface ReadWriteLock { Lock readLock(); Lock writeLock(); } ReadWriteLock定义了两个方法。readLock()返回用于读操作的锁,writeLock()返回用于写操作的锁

多线程以及JUC

梦想的初衷 提交于 2020-01-25 11:51:44
多线程以及JUC 一、JUC JUC包(java.util.concurrent) 很实用的工具类。 提供了可调,灵活的线程池。 今天学习的工具类每一种都有对应的有趣案例… 可惜… 1.ReentrantReadWriteLock 2.CountDownLatch 3.CyclicBarrier 4.Semaphore 二、多线程 2.1、线程和进程 1.程序:是一段静态的代码。 2.进程:是程序的一次执行过程,或者是正在运行的一个程序。 3.线程:是进程内部的一条具体的执行路径。若一个程序可同一时间执行多个线程,就是支持多线程的。 使用线程操作的好处: 1.将耗时间的任务放到后台去执行,例如载入、加载,实际上后台在疯狂的读数据。 2.提高计算机系统CPU的利用率。 2.2、线程安全及解决方式 多个线程同时共享同一个资源时,可能会出现数据冲突。 解决方式是加锁… lock或者synchronized ==>线程同步,多个线程共享同一个资源环境下,每个线程工作时不会受到其他线程的干扰称为线程的同步。 三、线程的创建方式 3.1、继承Thread类 3.2、实现Runnable接口 —隐匿内部类实现接口,可以使用lambda表达式。 3.3、使用Callable接口 需要借助FutrueTask类。 3.4、使用线程池 创建线程池的两种方式: 1

java并发编程(七)----(JUC)ReadWriteLock

白昼怎懂夜的黑 提交于 2020-01-25 07:24:56
前面我们已经分析过JUC包里面的Lock锁,ReentrantLock锁和semaphore信号量机制。Lock锁实现了比synchronized更灵活的锁机制,Reentrantlock是Lock的实现类,是一种可重入锁,都是每次只有一次线程对资源进行处理;semaphore实现了多个线程同时对一个资源的访问;今天我们要讲的ReadWriteLock锁将实现另外一种很重要的功能:读写分离锁。 假设你的程序中涉及到对一些共享资源的读和写操作,且写操作没有读操作那么频繁。在没有写操作的时候,两个线程同时读一个资源没有任何问题,所以应该允许多个线程能在同时读取共享资源。但是如果有一个线程想去写这些共享资源,就不应该再有其它线程对该资源进行读或写,也就是说: 读-读能共存,读-写不能共存,写-写不能共存 。这就需要一个读/写锁来解决这个问题。 ReadWriteLock简介 我们在JUC包可以看到ReadWriteLock是一个接口,他有一个实现类:ReentrantReadWriteLock,先让我们对读写访问资源的条件做个概述: - 读取: 没有线程正在做写操作,且没有线程在请求写操作。 - 写入: 没有线程正在做读写操作。 如果某个线程想要读取资源,只要没有线程正在对该资源进行写操作且没有线程请求对该资源的写操作即可。同样当有线程想要写资源,但是此刻有线程正在读取资源

Java多线程系列--“JUC锁”06之 Condition条件

僤鯓⒐⒋嵵緔 提交于 2020-01-25 06:30:40
先做总结: 1、为什么使用Condition条件? synchronized配合Object的wait()、notify()系列方法可以实现等待/通知模式。 Lock提供了条件Condition,对线程的等待、唤醒操作更加详细和灵活。 Condition的作用是对锁进行更精确的控制。Condition中的await()方法相当于Object的wait()方法,Condition中的signal()方法相当于Object的notify()方法,Condition中的signalAll()相当于Object的notifyAll()方法。 2、Condition条件实现原理: (1)lock.newCondition(),new一个ConditionObject对象,ConditionObject有一个单向等待队列 (2)condition等待队列:线程已经拿到锁,但是因为不满足某个条件,被放入等待队列并释放锁,不能获取锁    AQS同步队列:线程抢锁失败,被放入AQS阻塞队列,等前面线程释放锁之后自己再获取锁 (3)await():当前线程T加入条件等待队列 释放锁 park()当前线程    signal():当前线程T节点出条件等待队列 T节点加入AQS同步队列 unpark()T线程 一、Condition实现生产者消费者问题 class BoundedBuffer {

JUC源码分析-ThreadPool-jdk6

蓝咒 提交于 2020-01-23 16:06:42
ThreadPool源码分析-jdk6 execute方法分析 public void execute(Runnable command) { if (command == null) throw new NullPointerException(); //poolSize初始值为0,先启动corePoolSize数量的线程执行 if (poolSize >= corePoolSize || !addIfUnderCorePoolSize(command)) { //poolSize==corePoolSize 后 将task加入队列 if (runState == RUNNING && workQueue.offer(command)) { if (runState != RUNNING || poolSize == 0) ensureQueuedTaskHandled(command); } //如果队列容量不够 且 poolSize < maximumPoolSize 则直接启动 else if (!addIfUnderMaximumPoolSize(command)) reject(command); // is shutdown or saturated } } private boolean addIfUnderCorePoolSize(Runnable

JUC源码分析-ThreadPool-jdk7

无人久伴 提交于 2020-01-23 15:06:16
ThreadPool源码分析-jdk7 jdk7 并发包中的线程代码被重写。 线程池中原来代表线程数的poolSize 和代表状态的state被合并到ctl中 int类型共有32位,ctl的高三位用来表示状态,剩下的28位用来表示工作线程数 private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0)); //可以代表工作线程数的比特位数 private static final int COUNT_BITS = Integer.SIZE - 3; //工作线程的最大容量,28位可以表示最大的数值是 2^29-1 private static final int CAPACITY = (1 << COUNT_BITS) - 1; // runState is stored in the high-order bits //将线程池状态移动到高位 29~31位表示状态值 private static final int RUNNING = -1 << COUNT_BITS; private static final int SHUTDOWN = 0 << COUNT_BITS; private static final int STOP = 1 << COUNT_BITS; private static

JUC基础知识篇

て烟熏妆下的殇ゞ 提交于 2020-01-23 14:34:02
java并发实战 -- JUC线程高级 1.volatile关键字-内存可见性 内存可见性 问题是,当多个线程操作共享数据时,彼此不可见。 volatile关键字 :当多个线程操作共享数据时,可以保存内存中的数据是可见的。相较于synchronized是一种较为轻量级的同步策略。 注意: volatile 不具备互斥性 volatile不能保证变量的原子性 2.原子变量-CAS算法 i++的原子性问题: i++的操作实际上分为三个步骤"读-改-写"。 1 int i = 10; 2 i = i++;//10 1 int temp = i; 2 i = i + 1; 3 i = temp; 原子变量:jdk1.5后java.util.concurrent.atomic包下提供了常用的原子变量: 1.volatile保证内存可见性 2.CAS(Compare-And - Swap)算法保证数据的原子性  CAS 算法是硬件对于并发操作共享数据的支持  CAS 包含了三个操作数:   内存值V   预估值A   更新值B 当且仅当 V == A时,V = B,否则,将不做任何操作。 3.ConcurrentHashMap锁分段机制 java5.0 在java.util.concurrent包中提供了多种并发容器类来改进同步容器的性能。 ConcurrentHashMap

JUC高并发与线程安全(1)

我是研究僧i 提交于 2020-01-22 20:24:30
JUC高并发 1、谈谈你对volatile的理解 1.1volatile是Java虚拟机提供的轻量级的同步机制 1.1.1保证可见性 在内存模型中,线程将自身需要的对象数据从主机物理内存拷贝到线程工作内存(实际仍在物理内存,虚拟的划分约定),当线程对数据的修改经历三个步骤: 从物理内存拷贝数据到工作内存 在执行线程中修改数据 将数据写回物理内存 数据写完后,需要及时的通知其他需要此对象的线程,“该数据已更改,请重新加载”,这就是数据可见性 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8gEIEbLQ-1577715678426)(C:\Users\Kin\AppData\Roaming\Typora\typora-user-images\1577408098733.png)] 验证可见性 class Mydata { int num = 0 ; //添加volatile关键字再次测试 //volatile int num=0; public void initTo10 ( ) { this . num = 10 ; } public void numPlusPlus ( ) { this . num ++ ; } } public class VolatileDemo { public static void main ( String [ ]

【JUC-06】JUC—阻塞队列根接口BlockingQueue原理及应用

China☆狼群 提交于 2020-01-20 22:38:02
文章目录 1. 源码解析 1.1 类接口 1. 2 接口概况解析 1.3 主要用途 1.4 主要实现类 前言:阻塞队列是高并发场景中使用较多的接口,本身提供了很多功能并且很利于生产者-消费者的实现。 1. 源码解析 1.1 类接口 BlockingQueue本身类结构如下: 本质上可当做队列,主要实现了 queue 接口,因此具有队列的先进先出(FIFO)功能,因此从方法而言,具有 Queu 及 Collection 接口方法。 1. 2 接口概况解析 本质上是一个队列,但是与普通队列有不同之处,阻塞队列,只有队列非空(有元素)时才可以获取元素,当队列非满的时候才可以添加元素,否则只能阻塞等待。 BlockingQueue常见的操作可以划分为以下四种: 操作失败时抛出异常 操作失败时抛出特定的值(null或者false) 操作失败时会阻塞当前线程直到操作成功 操作失败时会阻塞一定的时间,然后放弃 功能/出错处理 抛异常 返回特定值 阻塞 超时放弃 插入 add(e) offer(e) put(e) offer(e, time, unit) 移除 remove() poll() take() poll(time, unit) 插入 element() peek() \ \ BlockingQueue 不接收空值,当该接口实现类,试图添加( add()、 put()、 offer()