为大家提供有意义,有帮助的技术文档,是本人最迫不及待的事,理解的不好的地方,希望大家指点帮助,后期会不断更新,维护,感激不尽!
下面就本人理解深入分析多线程环境下的并发问题
多线程环境下,我们至少需要认真考虑两个核心问题:互斥,通信,死锁
第一个问题:互斥
为了解决多线程并发造成的线程安全问题,我们需要实现不同线程之间对某个对象或者代码块的互斥访问,实现互斥的方式有很多种,首先我们看大家最熟悉的同步(synchronized)
A:synchronized:
实现同步的原理:
当一个线程进入同步代码块后,同步块在已进入的线程完成之前,会一直阻塞后面的线程进入,由于java中线程是映射到操作系统的原生线程上,如果要阻塞或者唤醒某条线程,都需要借助操作系统来帮忙,这就需要从用户态转换成核心态,花费处理时间,对于代码简单的同步块,状态转换消耗的时间,比代码执行的时间还要长,这样就得不偿失了,所以同步是一种很重量级的操作,只有必要时,才使用
B:上锁
Lock lock = new ReentrantLock();
锁提供两种特性:互斥和可见
互斥能阻止其他线程进入,可见使得当前线程对数据进行操作的结果被后续线程看见,避免发生线程安全问题,实现数据共享
重入锁有个很好的功能,在某种程度上可以有效的避免死锁,当一个线程长期占有锁不释放时,其他的线程会放弃等待改做其他事情
C:采用一个信号灯
new Semaphore(1);
信号灯除了可以实现同步还能控制并发的数量
D:使用Volatile关键字
volatile可以看着是一种轻量级的同步方式,他具备可见性,因为可以称它为易变,但是他不具备有原子性,
volatile不像锁那样造成阻塞,在某种情况下,读操作远大于写操作的时候,能够大大提高性能,前面提到它的安全性较低,因此他适合以下两种场景:a:对变量的写操作不依赖于当前值。
b:该变量没有包含在具有其他变量的不变式中。
E:最后,对于互斥的三点忠告
1,高并发时,防止重入,应循环检查当前状态
2,在写锁释放前lock读锁,会将写锁降级为读写锁
3, 无论如何,最终需要释放锁
《今天有事,未完待续,大家见谅》