标签:获得 tst atom 有序 依赖关系 失败 and 否则 管程
可见性:一个线程对共享变量的修改,另外一个线程可以立即看到.
示例:
int i = 0;
// 线程1
i = 10;
// 线程2
j = i;
// 若执行顺序是:线程2先执行,线程1再执行,则j=0
// 若线程1先执行,线程2再执行,则j=10
// 执行赋值语句时: 先从内存读取当前值到高速缓存中,修改后,再将数值写入到内存中.
原子性:一个操作或多个操作要么全部执行并且执行过程不被打断,要么都不执行.
示例:转账问题:A给B转账.A的余额减少,B的余额增加.两个动作必须都成功或都失败.
有序性:程序执行的顺序按照代码的先后顺序执行.
指令重排序(instruction reorder):程序中的代码顺序与实际执行的顺序并不一定是一致的.
三种类型的重排序:
流程:
源代码 ==> 编译器优化重排序 ==> 指令级并行重排序 ==> 内存系统重排序 ==> 最终执行的指令序列
volatile
关键字保证可见性.(被volatile
修饰的共享变量保证其修改后会被立即更新到内存,而普通变量修改后写入内存时间是不确定的)volatile
或synchronized
和Lock
保证有序性.(synchronized
和Lock
保证同一时刻只有一个线程执行同步代码,相当于顺序执行.)unlock
操作先于同一个锁的lock
操作.volatile
变量规则(Volatile Variable Rule): 对一个volatile
变量的写操作先于读操作.start()
方法调用先于此线程的所有动作.join()
方法,则该线程在另外线程执行结束后再继续执行.interrupt()
方法先于被中断的线程检测到中断事件的发生.finalize()
方法前.分类:
final
关键字修饰的基本数据类型.String
类型Number
部分子类: Long,Double,BigInteger,BigDecimal.示例:
// 使用Collections.unmodifiableList()获得一个不可变的集合
ArrayList<Integer> list = new ArrayList<>();
List<Integer> unmodifiableList = Collections.unmodifiableList(list);
unmodifiableList.add(1);
/* 底层直接将add改写成抛出异常
public void add(int index, E element) {
throw new UnsupportedOperationException();
}
*/
任何时刻都不需要额外的同步措施.
示例:
// ConcurrentHashMap是线程安全类,但是多个指令顺序执行时,
// 不能保证同一线程的不同指令连续执行而不被其他线程打断
ConcurrentHashMap chm = new ConcurrentHashMap<Integer,Integer>();
@Test
public void test() throws InterruptedException {
Thread t1 = new Thread(()->{
for (int i = 0; i < 10; i++) {
chm.put(i,i);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
Thread t2 = new Thread(()->{
for (int i = 0; i < 10; i++) {
chm.put(i,i+1);
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t1.start();
t2.start();
TimeUnit.SECONDS.sleep(2);
Iterator iterator = chm.entrySet().iterator();
while (iterator.hasNext())
System.out.println(iterator.next());
}
对象本身不是线程安全的,但通过适当的同步手段保证并发执行时正确的执行.
无论采取何种同步措施,都无法在多线程下并发使用.
synchronized
和ReentrantLock
.基于冲突检测的乐观并发策略:
unsafe
的CAS操作实现的.AtomicStampedReference
,通过变量的版本保证CAS的正确性.无同步方案:
ThreadLocal
,服务器,客户端的请求响应可以使用线程本地存储解决线程安全性问题)ThreadLocal
ThreadLocal
有一个ThreadLocalMap
对象.set()
方法,则先得到线程的ThreadLocalMap
对象,在进行插入操作.remove()
.参考:
标签:获得 tst atom 有序 依赖关系 失败 and 否则 管程
原文地址:https://www.cnblogs.com/truestoriesavici01/p/13217274.html