Java并发编程笔记

来源:互联网 发布:cs编程里包括什么 编辑:程序博客网 时间:2024/05/15 04:40

1.线程安全主要关注的问题:原子性和可见性。

所谓原子性,是指它要么完整的被执行,要么完全不执行。对于多线程来说,可以理解为,对于其他线程而言,它看到的是要么完整的被执行,要么完全不执行,而不会看到中间状态。实现原子性的主要方法有:原子变量:AtomicInteger,AtomicReference等;加锁,包括使用synchronized关键字;

所谓可见性,是指对于多个线程共享的变量,当一个线程做了修改之后,其他的线程在读取的时候能够立即看得到。实现可见性的主要方法有volatile 关键字;原子变量;加锁,包括使用synchronized关键字;

2.实现线程安全的方法:

原子变量;加锁;线程封闭,例如ThreadLocal;类封闭,使得变量完全封闭在类中,对外不可修改;使用final关键字使得类的各个状态为不可变,这样一定是线程安全的。

3.使用线程安全的类构造出来的代码不一定是线程安全的,使用非线程安全的类构造的代码也不一定是非线程安全的。

前者的例子:

private static AtmoicInteger count=new  AtomicInteger(0);

public increaseTwice(){

count.getAndIncrease();

count.getAndIncrease();

}

AtmoicInteger 是线程安全的, 但是由于对count的两次操作没有加锁,这段代码仍然不是线程安全的。

后者的例子:将类放到ThreadLocal中使用,一定是线程安全的。但是这样也失去了共享的可能。


4.Atomic变量的实现机制:其实Atomic是对Unsafe的一个封装,装饰器模式。对于最基本的操作,例如getAndAdd,getAndIncrease,compareAndSet等都是调用Unsafe对象的相关方法。只有getAndUpdate(IntUnaryOperator updateFunction),需要传入一个lambda表达式,Atomic采用了乐观锁来保证原子性。

而对于其他方法,在Unsafe中的实现,只有最基本的compareAndSwap是使用jni调用更底层的C(C又调用汇编,test and set指令),其余的是Unsafe封装的一个乐观锁。

其中的一段代码:

    int i;     do     {       i = getIntVolatile(paramObject, paramLong);     } while (!compareAndSwapInt(paramObject, paramLong, i, i + paramInt));     return i;

5. 同步的基础构建模块

BlockingQueue; CountDonwLatch;Barrier(栅栏);信号量;其实现都依赖于AbstractQueuedSynchronizer


0 0
原创粉丝点击