![](https://img-blog.csdnimg.cn/20201014180756925.png?x-oss-process=image/resize,m_fixed,h_64,w_64)
多线程
文章平均质量分 57
java相关的多线程知识
多多睡觉11
这个作者很懒,什么都没留下…
展开
-
[Java]Java线程的六种状态和切换的条件
TERMINATE:这个状态对应的是thred在内核的pcb已经完成了任务后,被销毁了,但是java中的thread对象并没有被释放,此时java为了表示这个对象的状态,就产生了这个TERMINATE这个状态。RUNNABLE:RUNNABLE状态表示java中的thread已经被创建了,且已经被start了,在内核中也有与thred对应的pcb被创建,并且这个pcb的状态是运行状态或者就绪状态;原创 2023-04-10 12:19:07 · 97 阅读 · 0 评论 -
[java]线程安全问题
java编译器在运行代码时有时会对代码的执行进行优化,比如一个大量的循环的读取同一个变量线程代码,正常情况下,每次读取都要在内存中去取得该变量的值,但是编译器在判断这个变量每次都只是被读取,并没有被修改后,它就做了一个大胆的决定但是java编译器优化后,它只有第一次读取去内存中读,第一次读取完之后,他将读取后的值存放在cpu内部,以后每次读取都从cpu内部读取,(因为从cpu读取比从内存读取的速度快得多,所以这提高了代码的运行效率)(3)原子性,修改操作的是可拆分的,导致脏读问题。原创 2023-04-16 14:21:57 · 321 阅读 · 0 评论 -
wait和notify的功能和使用注意事项
notify函数也是object实现的方法,哪个对象调用notify就是唤醒一个正在那个对象上wait的线程,notify也要在synchronized修饰的方法或者代码块里调用,调用的对象也是被加锁的对象。wait和notify就是控制线程执行顺序的两个方法,这两个方法是基础父类Objec的成员方法,所以所有的类都能调用这个两个方法;(2)sleep方法被唤醒是通过中断调用异常唤醒,本质上是错误逻辑,wait方法被唤醒是正常的函数调用,并没有发生错误;第一:释放调用wait方法对象的锁。原创 2023-04-16 23:36:15 · 738 阅读 · 0 评论 -
[java]线程池
但是操作系统也还有其他的工作要做,操作系统面向了所有此时正在运行的软件程序并且操作系统需要维护一些操作系统的底层逻辑,当多个程序都调用api时,每个程序的调用什么时候执行是由操作系统决定的,对用户程序来说,这些调用是不可控的,对操作系统来说,这些调用也会增加操作系统的负担,所以一般认为,如果一个系统内核执行的任务被安排在用户态执行,这项任务就变得高效起来。线程是为了降低进程的调度开销而出现的,线程比进程更轻量,线程是被包括在进程里面的,一个进程可以有多个线程,这多个线程共享进程的内存空间等资源。原创 2023-04-27 20:56:44 · 43 阅读 · 0 评论 -
单例模式和工厂模式
此时编译器先将地址赋值给了引用,再将实例的内容放入内存空间,由于new操作不是原子的,所以完全有可能,new被编译器优化完执行顺序后,代码执行完3,就调度其他线程了,其他线程此时调用get方法,先判断lazyman是否为null,由于3步骤已经将内存地址赋值给了引用,所以get直接返回了这个引用,这个线程此时去使用这个引用时,操作的是一片完全是错误内容的空间,出现了线程安全问题。静态的类对象和静态的get方法保证了只要这个类被加载,这个对象就会存在,使用类名这个类对象就能被找到;原创 2023-04-25 22:47:20 · 211 阅读 · 0 评论 -
java中的线程死锁问题
不可重入是指,对一个线程对一个对象加锁之后,在释放锁之前,又想对这个对象进行加锁,但是此时这个对象已经有锁了,就会陷入等待这个锁释放,但是第一个锁本身就是被线程本身加锁的,线程陷入了死锁,这个锁的特性就被称为不可重入锁,java的synchronized是可重入锁,不会出现这个问题。还是线程甲乙和锁ab,将锁a编号为1,锁b编号为2,此时甲乙都想申请锁a和b,他们需要现申请a,在申请b,只要甲线程申请到a,那b也只能被甲线程申请,因为乙必须先申请到a,才能申请b,而a已经被甲申请了,乙只能等待。原创 2023-04-15 23:11:31 · 79 阅读 · 0 评论 -
Cas的功能和应用
cas比较的原数据和被记录下的数据的大小来判断原数据是否在被记录下来之后发生了改变, 但是如果原数据A被记录下来后,先被改变成了B,然后又被改回了A,此时cas还是认为原数据A没有被改变,会直接执行交换的操作。cas作为while的循环条件,只有当cas返回true时,循环才会结束,线程就获得了锁,否则cas返回false,while循环就一直循环。版本号法:为每个原数据都设置一个版本号,原数据改变一次,版本号就递增,版本号永远不会重复,此时根据版本号来比较数据是否改变,就不会出现ABA问题。原创 2023-05-06 17:03:43 · 402 阅读 · 0 评论 -
[Java]synchronized的内部实现策略
一般情况下,锁的粒度是越小越好,毕竟加了锁的代码块就不能并发执行,影响了并发的程度,但是如果两个加锁的代码块挨得很近,中间只有几句代码,其实不如直接将整个代码都加锁,因为加锁和解锁也是有开销的。轻量级锁是自旋锁,偏量锁升级后,被阻塞的线程的synchronized也升级成自旋锁,此时被阻塞的线程会一直循环判断这个锁时候被释放,被释放了就马上获取锁。synchronized在六种锁策略中既是乐观锁又是悲观锁,既是轻量锁也是重量锁,既是自旋锁又是挂起等待锁,是互斥锁,是非公平锁,是可重入锁。原创 2023-05-05 23:26:30 · 46 阅读 · 0 评论 -
[Java]信号量semaphore
信号量可以实现共享锁,通过设置信号量的数目控制可以同时使用资源的数目。当所有资源已经被申请完,且没有资源被释放时,再次申请资源会阻塞。五、semaphore的应用。四、申请资源失败(阻塞)原创 2023-05-06 23:34:51 · 50 阅读 · 0 评论 -
六种锁策略
在使用乐观锁加锁时,不会直接加锁,而是首先取得现在加锁数据的状态,然后在需要修改被加锁的数据的时候,比较此时的数据和刚刚加锁时取得的数据是否相等,相等则说明没有其他线程对加锁数据进行修改,此线程就直接修改数据,不相等则说明其他线程在这期间修改了这个数据,此时就进行回滚,重新尝试修改数据。不可重入就是同一个线程不可以对一个锁重复加锁,会出现加了一个锁之后,此时还要再加一次这个锁,但是这个锁之前已经被这个线程获取了,此时第二次就获取不到这个锁,产生了死锁。一般情况下,乐观锁也是轻量锁,悲观锁也是重量锁。原创 2023-05-05 23:00:47 · 43 阅读 · 0 评论 -
[Java]Callable接口
上面的代码创建了一个以call方法作为任务的线程,因为call方法在一个另一个线程中运行,这个call方法的返回值会存放在featureTask对象中,调用fertureTask的get()方法可以获得call方法的返回值,如果此时call方法的任务还没有做完,get方法将阻塞调用了get方法的线程,直到call方法返回结果才会唤醒。FeatureTask用来保存call方法的返回值,等待call方法执行完毕,并获得call方法的返回值。一、Callable接口的实例化。原创 2023-05-06 22:21:40 · 549 阅读 · 0 评论 -
[Java]ReentrantLock的使用
在实际的编程中,代码往往有很多分支,调用了lock之后必须要调用unlock其他地方才能调用lock加锁,但是由于需要手动解锁,所以很有可能忘了unlock,为保证每个lock都能被unlock,使用trycatch中的finally代码块来确保最后都会释放锁。普通的lock方法如果有其他线程已经lock了,那线程就会阻塞并死等,但是使用trylock方法,就只会尝试加锁,然后返回true或者false来表明是否加锁成功,加锁失败就放弃加锁,也不死等。(3)提供了公平锁的版本。原创 2023-05-06 23:15:42 · 723 阅读 · 0 评论 -
[Java]CountDownLatch类的使用
CountDownLatch是用来同步多个线程的执行顺序的,如果有多个线程在执行,有任务需要等这几个线程都执行完了再执行,此时可以在这个任务前面将这几个前驱线程的所有join都调用一遍,但是如果线程的数目越来越多,join也越来越多,这显然增加了编程的繁琐程度也容易出错。注意:有序countDown方法可以放在线程run方法的任意位置,其实后续任务不一定是要前驱贤臣都执行结束才继续执行,也可能前驱任务执行了一部分就可以执行了。countDown和await方法配合使用才能达到等待前驱线程完成的效果。原创 2023-05-07 14:49:34 · 191 阅读 · 0 评论