Q:什么是线程安全问题?
A:就是将多条操作共享数据的线程代码封装起来,当有线程在执行这些代码的时候,其他线程是不可以参与运算的。
Q:线程安全问题如何产生?
A:所谓线程安全都是因为 全局变量、静态变量被多个线程引用并同时更改共享数据导致的。所以如果对变量进行只读操作是可以避免安全问题的。
Q:方法内部的局部变量,如果方法被多个线程调用,也就是多并发的时候,这个方法是否存在线程安全问题?
A:不存在安全问题。因为这个局部变量被多个线程调用时候,都会新开内存。所以不会导致多线程同时更改同一块内存数据的问题。所以这样写没问题。
局部变量会存放在栈里。如果一个变量需要跨越方法的边界,就必须创建在堆里。
每个线程都有自己独立的调用栈,局部变量保存在各自独立的调用栈内,所以局部变量的线程是安全的。
Q:什么是线程封闭?
方法里的局部变量,因为不会和其他线程共享,所以不会存在并发问题。这种解决问题的技术也叫做线程封闭。官方的解释为:仅在单线程内访问数据。由于不存在共享,所以即使不设置同步,也不会出现并发问题!
Q:如何解决线程不安全问题?
A:有三种方式:分别是
- 同步代码块
- 同步方法
- 锁机制(Lock)
(1)同步代码块:
synchronized(同步锁)
{
//方法体
}
(2)同步方法:给多线程访问的成员方法加上synchronized修饰符
public synchronized void test(){
//方法体
}
实际上,同步代码块和同步方法差不了多少,在本质上是一样的,两者都用了一个关键字synchronized,synchronized保证了多线程并发访问时的同步操作,避免线程的安全性问题,但是有一个弊端,就是使用synchronized的方法/代码块的性能比不用要低一些,因此如果要用synchronized,建议尽量减小synchronized的作用域。
注意:
不要使用synchronized修饰run方法,修饰之后,某一个线程就执行完了所有的功能. 好比是多个线程出现串行.
解决方案:把需要同步操作的代码定义在一个新的方法中,并且该方法使用synchronized修饰,再在run方法中调用该新的方法即可.
(3)同步锁:(锁机制)
为了保证每个线程都能正常执行原子操作,Java引入了线程同步机制.也称为同步监听对象/同步锁/同步监听器/互斥锁。
Lock 锁机制实际上:对象的同步锁只是一个概念,可以想象为在对象上标记了一个锁,谁拿到锁,谁就可以进入代码块,其他线程只能在代码块外面等着,而且注意,在任何时候,最多允许一个线程拥有同步锁.
Q:同步锁、互斥锁、读写锁、自旋锁有啥区别吗?
A:
互斥锁(lock):ABCD,一次只能其中一个线程,多个线程争抢资源是乱序。
同步锁:ABCD,一次只能执行一个线程,这些线程有序执行。
读写锁(ReadWriteLock):支持单个写线程和多个读线程的锁。该锁的作用主要是解决并发读的性能问题,使用该锁,可以大大提高数据并发访问的性能,只有在写时,才会阻塞所有的读锁。
自旋锁:自旋锁的使用模式和互斥锁很类似。只是在加锁后,有线程试图再次执行加锁操作时,线程不会被阻塞,而处于循环等待的忙等状态(CPU不能做其它事情)。
互斥锁同步锁两者的区别就是:
互斥是通过竞争对资源的独占使用,彼此之间不需要知道对方的存在,执行顺序是一个乱序。
同步是协调多个相互关联线程合作完成任务,彼此之间知道对方存在,执行顺序往往是有序的。但也是多个线程不能同时进行,按照某个顺序依次进行(也是一种互斥)
网友评论