什么是线程?它是干什么的?确定不进来看下?

您所在的位置:网站首页 柳叶笔是用来干嘛的呢 什么是线程?它是干什么的?确定不进来看下?

什么是线程?它是干什么的?确定不进来看下?

2024-03-21 12:57| 来源: 网络整理| 查看: 265

窗外的日子热火朝天,窗里的人儿悠然自在,一口西瓜想起来线程,为什么呢?这就要从下面的故事说起了。 一个炎热的夏天,屋里 的人儿疯狂的打着电脑,忽然之间一顿黑屏,我的乖乖,电脑咋这么烫手呢。这个时候看到一本神器的书本,线程是怎样工作的,好吧,我就看会书吧。要了解线程就要先了解进程,什么是进程呢?

进程是系统进行资源分配和调用的独立单位每一个进程都有自己的内存空间和系统资源

这样啊,那线程和进程什么关系啊,兄弟?怎么可能吗,这明明是亲子关系嘛,那谈一下什么是线程?

线程是进程中的单个顺序控制流,是一条执行路径多个线程堆空间是共享的,栈空间是独立的(就因为这一句话,那个高并发,那个线程锁就让人开始头疼了)

这儿有一个小特殊哦,java程序的进程中最少有俩个线程,一个是主线程main(),还有一个是垃圾回收机制线程。

一、1.1 实现线程的三种方式:

继承Thread()类,重写run()方法实现runnable接口,重写run()方法实现callable接口,重写call()方法 run()方法和call()方法是用来封装被线程执行的代码,call方法有返回值,并且还能声明抛出异常。 start():启动线程;然后由JVM调用此线程的run()方法

既然创建了多个线程,那多个线程又是怎么被调用的呢? 1.2 线程有俩种调度方式:

分时调度模型:所有线程轮流使用 CPU 的使用权,平均分配每个线程占用 CPU 的时间片抢占式调度模型:优先让优先级高的线程使用 CPU,如果线程的优先级相同,那么会随机选择一个,优先级高的线程获取的 CPU 时间片相对多一些

我们可以设置线程的优先级,不过这并不能保证优先级高的线程一定先执行,因为线程是随机性的,我们只是增大了此线程被调用的概率。

在这里插入图片描述 守护线程:java中有俩种线程,一种是用户线程,另一种是守护线程。区别就是主线程不存在或停止,用户线程不停止,守护线程停止 在这里插入图片描述 那么当线程在执行的时候我们又该怎么去控制它呢?那么往下看 1.3线程控制 线程等待:

sleep():它是Thread的方法,使当前正在执行的线程停留指定的毫秒数,当指定的时间到了又会自动恢复运行状态,使用此方法并不会释放当前锁对象wait():它是objecct的方法,方法会使持有该对象的线程把该对象的控制权交出去,然后处于等待状态。join():等待这个线程死亡其它线程再继续执行yield():让当前正在运行的线程回到可运行状态,以允许具有相同优先级的其他线程获得运行的机会notify 方法会通知某个正在等待这个对象的控制权的线程继续运行notifyAll 方法会通知所有正在等待这个对象的控制权的线程继续运行。

线程停止:

设置退出标志,使线程正常退出。使用interrupt()方法中断线程。使用stop方法强行终止线程

1.4 线程的生命周期 查看Thread源码共有六种状态: 1.新建(NEW) 2.可运行状态(RUNNABLE) 3.阻塞状态(BLOCKED) 4.无限等待(WAITING) 5.计时等待(TIMED_WAITING) 6.被终止(TERMINATED)

在上面了解线程是什么,并且怎么去控制它的,那么下面就来谈一谈 1.5多线程并发的三个特性:

原子性: 即一个操作或者多个操作 要么全部执行并且执行的过程不会被任何因素打断,要 么就都不执行可见性:当多个线程访问同一个变量时,一个线程修改了这个变量的值,其他线程能够立即 看得到修改的值有序性:程序执行的顺序按照代码的先后顺序执行

这些线程都是怎么工作的,为什么会有这三个特性呢,那首先就下知道下面这个java内存模型: 概念: java内存模型就是一种符合内存模型规范的,屏蔽了各种硬件和操作系统的访问差异的,保证了java程序在各种平台下对内存的访问都能保证效果一致的机制和规范。简称JMM,记住它只是一个抽象的概念。 那么线程去操作内存就有一些基本规则:

1.第一条关于线程与主内存:线程对共享变量的所有操作都必须在自己的工作内存(本地内存)中进行,不能直接从主内存中读写 2. 第二条关于线程间本地内存:不同线程之间无法直接访问其他线程本地内存中的变量,线程间变量值的传递需要经过主内存来完成

哦,原来线程进行操作是复制主内存的共享变量到本地内存进行操作啊,有没有发现什么特点,就是线程间变量值的传递需要经过主内存来完成,那么就是就是说即线程中的本地变量对其它线程是不可见的,这样想想如果传递不及时肯定是要出现很多差错的啊,java的并发编程就由此而生。

内存可见性及解决方法

看了上面想必应该对内存可见性有个模糊的认知了,线程在本地内存修改了共享变量(主内存的变量)其它线程并不知道啊,内存可见性就是一个线程对共享变量值的修改,能够及时的被其他线程看到。 太聪明了,怎么能让其他线程看见呢? 隔我说那就暴力点,强制线程每次读取该值的时候都去“主内存”中取值。

1. synchronized synchronized可以保证并发的原子性,可见性,有序性。 在这里插入图片描述 1.1同步原理 Java中每一个对象都可以作为锁,这是synchronized实现同步的基础: 1.普通同步方法,锁是当前实例对象this 2. 静态同步方法,锁是当前类的class对象 3. 同步方法块,锁是括号里面的对象 既然sychronized是啥呢?重量级锁,效率不高,不过后实现各种优化,让这个小胖子稍微瘦了点。为什么是重量级说呢,既然有重量级锁就有轻量级锁吧,哎,聪明啊小苗同学,既然你问了就简单说一下吧。

2.锁优化

1.自旋锁:所谓自旋锁,就是让该线程等待一段时间,不会被立即 挂起,看持有锁的线程是否会很快释放锁。怎么等待呢?执行一段无意义的循环即可(自旋)。

2.适应自旋锁:所谓自适应就意味着自旋的次数不再是固定的,它是由前一次在同一个锁上的自旋时间及锁的拥有者的状态来决定。

3.锁消除: JVM检测到不可能存在共享数据竞争,这是JVM会对这些同步锁进行锁消除。锁消除的依据是逃逸分析的数据支持。

4.锁粗化:就是将多个连续的加锁、解锁操作连接在一起,扩展成一个范围更大的锁

5.偏向锁:轻量级锁的加锁解锁操作是需要依赖多次CAS原子指令的。而偏向锁只需要检查是否为偏向锁、锁标识为以及ThreadID即可,可以减少不必要的CAS操作。

6.轻量级锁:当关闭偏向锁功能或者多个线程竞争偏向锁导 致偏向锁升级为轻量级锁,则会尝试获取轻量级锁。轻量级锁主要使用CAS进行原子操作

7.重量级锁:重量级锁通过对象内部的监视器(monitor)实现,其中monitor的本质是依赖于底层操作系统的Mutex Lock(互斥锁)实现,操作系统实现线程之间的切换需要从用户态到内核态的切换,切换成本非常高。

哇,原来是这样的,不实际操作或者解决,反正不太懂,先模糊知道个概念,大体有个认知就可以了。 上面说sychronized是可以解决内存可见性,不过它是重量级锁,性能方面会有下降,下面我们来认识下volatile变量:

3.Volatile 一个变量如果用volatile修饰了,则Java可以确保所有线程看到这个变量的值是一致的,如果某个线程对volatile修饰的共享变量进行更新,那么其他线程可以立马看到这个更新,这就是内存可见性。 这么一看只需要在共享变量前加一个关键字就行了呗,太简单了吧,的确哈,不过真正用好可没有那么简单哦。 在这里插入图片描述 注意: 虽然Volatile 关键字可以让变量在多个线程之间可见,但是Volatile不具备原子性。

一看天不早了,是时候入侵了,来人伺候更衣,线程就先聊到这儿,面对很大的高并发,又要解决性能问题,各位大神可是费劲心思,小生也看看也是害怕啊,哈哈,下期我们继续,在整理的过程中小苗子也是印象深刻,很多地方还有不足,睡觉吧。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3