java并发编程
并发编程知识分享
卷土重来…
抱怨和放弃很容易却让人一文不值,坚持和努力很难却能过上想要的生活!
展开
-
42.AQS
属性表示资源的状态:独占模式,共享模式。子类需要定义如何维护这个状态,控制如何获取锁和释放锁。7.条件变量来实现等待,唤醒机制,支持多个条件变量,类似于Monitor的WaitSet。4.独占模式:只有一个线程能访问这个资源。使用Synchronized锁就是独占模式。1.AQS, AbstractQueuedSynchronizer,是。5.共享模式:允许有多个线程访问资源。2.阻塞式的锁就类似于Synchronized锁。,类似于Monitor的EntryList。tryAcquire 获取锁。原创 2024-04-18 20:19:46 · 325 阅读 · 0 评论 -
41.ScheduledThreadPool线程池实现定时任务
利用ScheduledThreadPool线程池实现定时任务。LocalDateTime的使用;Duration的使用;原创 2024-04-17 22:54:48 · 448 阅读 · 0 评论 -
39.原子更新器
保证对对象属性的更新具有原子性。原创 2024-04-07 22:50:23 · 118 阅读 · 0 评论 -
38.java8函数式接口
Supplier<T> 提供者,无中生有。无参数,有结果。 Function<T> 函数。一个参数,一个结果。 BiFunction(参数1,参数2)->结果。 Consumer消费者,一个参数没有结果。 BiConsumer 两个参数没有结果。原创 2024-04-07 22:32:00 · 316 阅读 · 0 评论 -
37.ABA问题
通过AtomicStampedReference的版本号,可以知道数据改了多少次。但是如果在这个过程中,A变成D然后又变成A, 那么再调用compareAndSet去改变也能修改成功B。这个过程中A->D->A,程序是感知不到的。如果主线程希望,只要有其他线程动过这个共享变量,那么自己cas操作就算失败,这时比较值是不够的,需要加入版本号。上面的代码:主线程仅能判断共享变量的值是否与最初的A是否相同,不同感知这种从A变成了B,又变成了A的情景。就会先比较原来的值是否为A,如果为A则修改成功,否则修改失败。原创 2024-04-05 20:42:32 · 347 阅读 · 0 评论 -
36.基于CAS实现的java类
JUC, java.util.concurrent并发工具包下。原创 2024-04-05 19:36:34 · 332 阅读 · 0 评论 -
35.无锁(乐观锁)CAS
synchronized是基于悲观锁的实现,防着其他线程来修改共享变量,我上了锁你们都别改,我改完解开锁,你们才有机会。无锁的情况下,即使重试失败,线程始终在高速运行,没有停歇。CAS是基于乐观锁的实现,最乐观的估计,不怕别的线程来修改共享变量,就算改了也没有关系,我吃点亏再重试。1.因为没有使用synchronized,所以线程不会陷入阻塞,这是效率提升的因素之一。compareAndSet方法是原子的,不可分割的。,因为比较并交换,每次都需要读取共享变量最新的值来实现比较。的方式保护共享资源现成安全。原创 2024-04-05 15:43:37 · 332 阅读 · 0 评论 -
34.单例模式
静态内部类来创建单例-懒汉式。原创 2024-04-05 13:56:35 · 180 阅读 · 0 评论 -
33.Double checked locking
前提条件:如果Synchronized中的变量没有完全受Synchronized管理控制,那么就不能保证有序性,会发生指令重排序的问题。所以Synchronized是不能够保证有序性的,这个时候就需要给变量添加volatile关键字修饰,来保证变量的有序性,防止指令的重排序。前提条件:如果Synchronized中的变量完全受synchronized管理控制,那么就能够保证有序性,不会有发生指令重排序的问题。所以Synchronized是能够保证有序性的。synchronized到底能不能保证 有序性?原创 2024-04-05 11:05:28 · 353 阅读 · 0 评论 -
32.volatile保证指令有序性
jvm在不影响正确性的前提下,可以调整语句的执行顺序。多线程下这种指令重排会影响正确性,而单线程没有问题。volatile修饰就可以解决指令重排序。jvm调整指令执行的顺序叫做指令重排。JIT即时编译器做的一些优化。原创 2024-04-04 22:48:07 · 440 阅读 · 0 评论 -
31.volatile保证可见性
因为t1线程要频繁的从主内存中读取flag的值,JIT编译器会将flag的值缓存到自己工作内存中的高速缓存中,减少对主内存flag的访问,提高效率。1秒之后,main线程修改了flag的值并同步至主存,而t1线程永远从自己工作内存中的高速缓存中读取这个变量的值,结果永远是旧值。避免线程从自己的工作缓存中查找变量的值,线程操作volatile变量都是直接操作主存。volatile修饰的都是多个线程共享的变量,不会修饰局部变量,因为局部变量每个线程都有一份。volatile只能保证可见性,不能保证原子性。原创 2024-04-04 20:06:44 · 200 阅读 · 0 评论 -
30.多个线程交替执行
线程一输出a,5次;线程二输出b,5次;线程三输出c,5次;现在要求输出abcabcabcabcabc怎么实现?原创 2024-04-04 11:12:16 · 323 阅读 · 0 评论 -
29.使线程以固定顺序输出结果
【代码】29.使线程以固定顺序输出结果。原创 2024-04-03 22:29:18 · 434 阅读 · 0 评论 -
28.ReentrantLock-多条件变量
synchronized中也有条件变量,当条件不满足时进入WaitSet等待。ReentrantLock的条件变量比Synchronized强大之处在于它支持多个条件变量。原创 2024-04-03 22:02:40 · 560 阅读 · 0 评论 -
27.ReentrantLock
2.与synchronized相同点都支持锁的可重入。//获取锁try {//必须释放锁同一个线程如果首次获得了这把锁,因为它是这把锁的拥有者,因此有权利再次获取这把锁。如果是不可重入锁,那么第二次获得锁时,自己也会被锁挡住。原创 2024-04-02 23:24:52 · 611 阅读 · 0 评论 -
26.活锁、饥饿锁
两个线程,相互改变了对方结束条件,导致两个线程不能结束。执行时间也都是一样,导致两个线程永远不会结束。解决办法:将执行时间设置成不一样即可。原创 2024-04-01 23:20:02 · 759 阅读 · 0 评论 -
25.死锁
一个线程如果需要同时获取多把锁,就容易产生死锁。t1线程获得A对象锁,接下来想获取B对象的锁。t2线程获得B对象锁,接下来想获取A对象的锁。命令,可以查看当前正在运行的java进程。经典死锁案例:五位哲学家五根筷子吃饭。原创 2024-04-01 23:06:55 · 417 阅读 · 0 评论 -
24.park和unpark方法
调用unpark方法,_counter=1,_cond没有阻塞的线程,就结束了。然后调用的park方法,发现unpark=1,此时线程无需阻塞继续运行,然后设置_counter=0。当线程调用unpark的时候,把_counter设置为1,唤醒_cond阻塞队列中的线程,线程就恢复运行,又会把_counter设置为0。,就获得_mutex互斥锁,线程进入_cond条件变量阻塞,然后再设置_counter=0。,unpark先调用,park后执行也可以恢复线程。当线程调用park方法,检查_counter,原创 2024-03-27 22:20:49 · 507 阅读 · 0 评论 -
23.异步模式-生产者、消费者
1.与保护性暂停GuardedObject不同,不需要产生结果与消费结果的线程一一对应。3.生产者负责产生结果数据,不关心数据该如何处理,而消费者专心处理结果数据。4.消息队列是有容量限制的,满时不会再加入数据,空时不会再消耗数据。2.消费队列可以用来平衡生产和消费的线程资源。5.jdk中各种阻塞队列,就是采用这种模式。原创 2024-03-26 22:48:10 · 884 阅读 · 0 评论 -
22.保护性暂停扩展(一对一)
Futures就好比居民楼一层的信箱,每个信箱有房间的编号,左侧的t0,t2,t4就好比等待邮件的居民,右侧的t1,t3,t5就好比邮递员。如果需要多个类之间使用GuardedObject对象,作为参数传递不是很方便,因此设计一个解耦的中间类,这样不仅能够解耦。,还能够支持多个任务的管理。原创 2024-03-25 22:31:57 · 227 阅读 · 0 评论 -
21.同步模式-保护性暂停
1.可能会发生虚假唤醒的时候,reponse还是为null,满足条件继续进入下一次等待,如果等待时间不减去上次已经经历的时间,等待时间就会比实际设置的timeout的时间要长。3.如果有结果不断从一个线程到另一个线程,那么可以使用消息队列。1.如果线程t2执行的时间很长,那么线程t1就会一直等待结果。2.一个结果从一个线程传递到另一个线程,让他们关联同一个。4.join方法和Future的实现,采用的就是此模式。5.因为要等待另一方的结果,因此归类到同步模式。,用在一个线程等待另一个线程的执行结果。原创 2024-03-24 23:08:23 · 489 阅读 · 0 评论 -
18.买票问题
多个线程运行的地方,有ticketWindow和threadList两个变量,ticketWindow中有共享变量count的修改。threadList也是被多个线程共享并执行添加操作,但是Vector本身就是线程安全的,所以不用考虑。但是ticketWindow中的sell方法对共享变量count进行了修改操作,需要加锁来保证线程安全问题。原创 2024-03-10 21:24:50 · 500 阅读 · 1 评论 -
20.wait与sleep的区别
wait(long time)方法和sleep(long time)方法,都带有时间的方法,调用后线程都会进入。2.wait方法必须与synchronized配合使用,sleep可以不与synchronized配合使用。1.wait方法是Object类对象的方法,sleep是Thread类的静态方法。3.sleep在睡眠的同时不会释放对象锁,wait在等待的时候会释放对象锁。原创 2024-03-23 22:37:47 · 294 阅读 · 0 评论 -
19.wait方法与notify方法
wait(long timeout)有时限的等待,如果没有调用notify和notifyAll方法,时间到了就会结束等待。4.notifyAll方法是将WaitSet集合中的所有线程全部唤醒。wait方法不带参数,表示线程无限制的等待下去,直到notify方法或者notifyAll方法来唤醒。,才能调用这wait方法,notify方法,notifyAll方法。中,与其它线程一起参与竞争锁资源。,让EntryList中其他线程竞争去使用锁资源。1.当前线程持有锁时,如果调用。中的线程挑一个,放到。原创 2024-03-22 22:49:09 · 379 阅读 · 1 评论 -
17.线程实例分析
如果是引用对象,引用不能再修改,但是对象里面的属性还是可以被修改的。说明:SimpleDateFormat对象虽然是局部变量,但是foo方法是不确定的,如果foo方法被子类复写会开启一个新的线程,那就是线程不安全的。spring中默认的bean对象都是单例的,这里start又是成员变量,多个线程共享start变量,方法中对成员变量进行赋值和修改。dao类里面没有成员变量,只有局部变量,比如connection对象,每个线程都有属于自己的connection对象,所以是线程安全的。所以也是线程安全的。原创 2024-03-09 23:22:16 · 439 阅读 · 1 评论 -
16.线程安全的类
问题:String有replace,substring方法可以改变值啊?那么这些方法又是如何保证线程安全的?1.他们的每个方法是原子的,可以看到源码中方法都是加了synchronized对象锁的。线程安全指的是,多个线程调用他们同一个实例的某个方法时,是线程安全的。线程不安全,导致后一个put操作的值将前一个put操作的值覆盖掉了。上面两种类,内部的状态不可以改变,因此他们的方法都是线程安全的。所以,根本就没有改变value的值。2.注意他们多个方法的组合不是原子的。a.产生一个新的String。原创 2024-03-09 22:41:58 · 654 阅读 · 1 评论 -
15.变量的线程安全分析
如果他们没有被共享,则线程安全。如果他们被共享如果只有读操作,则线程安全。如果有读写操作,则这段代码是临界区,需要考虑线程不安全。如果线程0还未add,线程1remove就会报错。所以对共享资源list进行了读写操作,就会产生线程不安全的问题。就是在method2和method3方法上加锁synchronized即可。原创 2024-03-09 21:53:44 · 353 阅读 · 1 评论 -
1.并发和并行
并发和并行原创 2024-03-05 22:37:25 · 415 阅读 · 0 评论 -
2.创建线程的方式
【代码】2.创建线程的方式。原创 2024-03-06 20:33:41 · 431 阅读 · 0 评论 -
3.window系统下通过命令查看进程
window系统下通过命令查看进程原创 2024-03-06 21:39:51 · 341 阅读 · 0 评论 -
4.线程与栈的关系
线程与jvm内存结构中栈、栈帧、堆、方法区、程序计数器、局部变量表、返回地址;idea中多线程debug;原创 2024-03-06 23:07:58 · 486 阅读 · 0 评论 -
5.线程上下文切换
因为一些原因导致cpu不再执行当前线程,转而执行另一个线程的代码。原创 2024-03-07 21:03:30 · 573 阅读 · 0 评论 -
6.线程中常见的方法
start方法,run方法,getState方法,sleep方法,interrupt方法,yield方法,setPriority方法原创 2024-03-07 23:29:16 · 319 阅读 · 0 评论 -
7.线程中常见方法补充
join方法,wait方法,stop方法原创 2024-03-08 14:29:13 · 345 阅读 · 1 评论 -
8.两阶段终止模式
如果在sleep中被打断,就抛出异常,就在异常代码块中再次设置打断标记为true,即可停止监控线程。调用interrupted方法,会清楚打断标记,也就是false, 所以park方法第二次还可以让线程停下来。如果是isInterrupted方法,不会清除打断标记,也就是为true,那么park方法第二次是停不下来的。被打断后,如果清除标记为true, 调用了该方法后返回true,然后清除标记又会变成了false。stop方法会杀死线程,这可不行,如果该线程给某个资源加了锁,现成死掉了,资源都无法释放了。原创 2024-03-08 16:19:40 · 456 阅读 · 1 评论 -
9.线程中不推荐的方法
不推荐使用的方法,这些方法已过时,容易破坏同步代码块,造成线程。suspend方法,应该使用。stop方法,应该用。原创 2024-03-08 19:54:25 · 331 阅读 · 1 评论 -
10.守护线程
只要其他非守护线程运行结束了,即使守护线程的代码没有执行完,也会强制结束。2.Tomcat中Acceptor和Poller线程。java进程需要等待所有的线程都执行完,才会结束。原创 2024-03-08 21:14:29 · 273 阅读 · 1 评论 -
11.线程状态
1.初始状态2.可运行状态3.运行状态4.阻塞状态5.终止状态。原创 2024-03-08 22:04:08 · 369 阅读 · 1 评论 -
12.多线程解决泡茶
1.上面模拟了老王烧完开水后,小赵泡茶。如果反过来实现老王等小赵的茶叶拿来了,老王泡茶呢?代码最好适应两种情况。2.如果要模拟老王把水壶交给小赵泡茶,或者小赵把茶叶交给老王泡茶。我想泡茶,需要洗水壶,烧开水,洗茶壶,洗茶杯,那茶叶。线程一(老王):洗水壶1分钟,烧开水15分钟。线程二(小赵):洗茶壶,洗茶杯,拿茶叶4分钟。原创 2024-03-08 22:34:47 · 275 阅读 · 1 评论 -
13.线程安全问题
静态变量的自增自减不是原子操作,因为会产生多条字节码指令,分时系统多线程就容易产生指令之间的一个交错。1.阻塞式,synchronized对象锁,Lock。由于分时系统导致的线程安全问题。时发生指令交错,就会出现问题。对共享资源的多线程读写操作。多个线程对共享资源进行。,这段代码称为临界区。2.非阻塞式,原子变量。问题在于多线程访问了。取共享资源没有问题。一段代码内如果出现了。原创 2024-03-08 23:16:08 · 347 阅读 · 1 评论