共享模型的管理:
-
线程的阻塞,所以就有了cpu的时间片,尽可能的利用cpu:
- sleep:有时间限制的休息;
- wait:无时间的休息;
- io读写的阻塞;
-
临界区:Critical Section
- 多个线程的访问共享资源【主内存】的问题【并发问题】
- 多个线程对共享资源读写操作时发生了指令交错,所引发的原子性问题;
- 一段代码块如果存在对共享资源的多线程读写操作,则称这段代码为临界区;
- 多个线程的访问共享资源【主内存】的问题【并发问题】
-
竞态条件:Race Condition
- 多线程在临界区内执行,由于代码执行序列不同而导致结果无法预测,则称之为竞态条件;
-
多并发的上下文切换问题,解决方案:
-
阻塞式的:synchronized【对象锁,采用互斥的方式】,Lock
-
非阻塞式的:原子变量;
-
互斥和同步都可以采取:synchronized:
-
互斥:是保证临界区的竞态条件下,同一时刻只能有一个线程执行该代码;
-
同步:是由于线程执行的先后顺序不一致,需要一个线程等待其他线程运行到某个点;
//必须得保证是同意把锁; synchronized(对象锁) {//临界区 }
-
当线程来了后,发现临界区被锁上了,就会进行上下文切换陷入阻塞状态;
-
当线程结束后,会唤醒其余阻塞线程,又cpu的时间片决定给谁锁;
synchronized利用对象锁,保证的临界区的原子性;
-
方法上的synchronized
- 普通方法:锁住的是this;
- 静态方法:锁住的是类.class【Class对像】;
-
-
-
变量【主内存】的线程安全:
- 当不存在共享时,当只有读操作时,当仅为局部变量时,变量安全;
- 当存在读写操作时【临界区代码】,变量不安全;
- 线程中创建的对象,都会在堆中,当把这个对象引用暴露在其他线程的时候,那么其他线程也就能访问了【不安全】;
- private,finall的修饰符在一定程度上,保护了局部变量的安全性,使得继承子类,无法操作数据【开闭原则的闭】;
-
常见线程安全类:
- String【内部属性不可变】, Integer, StringBuffer, Vector, HashTable, java.util.conrrent【JUC】下的包;
- 单个方法具有原子性;
- 多个方法的组合不具有原子性;