多线程比较常见而且比较重要的问题
1:线程安全问题
在多个线程同时运行时发生的异常情况统称为线程安全问题。
线程安全问题在理想状态下,不容易出现,但一旦出现对软件的影响是非常大的。
产生原因&前提:
线程随机访问性
有多个线程并行
多个线程有共享数据
多个线程操作了共享数据
处理方式:
使用java提供的同步机制,使某一线程的完整动作执行完毕,其他线程再进行操作
ava同步机制:为解决同步问题而提供的工具
原子性操作:
在执行操作时,我们把一个完整动作可以称为一个原子性操作,是一个不可切割的动作。即不可被线程打断的操作。
synchronized 关键字:
同步代码块格式:
synchronized(锁对象){//该对象可以是任意对象
需要同步的代码;
}
锁:几个线程需要使用相同的锁对象进行同步操作,使用不同的锁是无法完成同步操作的。
Synchronized内需要同步的代码即为一个原子性操作。
同步方法:方法上声明,将所在对象作为默认锁,即this。
同步静态方法:将方法所在类作为默认所,即XX.class。
优点:解决了多线程安全问题
缺点:当线程相当多时,因为每个线程都会去判断同步上的锁,这是很耗费资源的,无形中会降低程序的运行效率。对于一个简单操作,单线程速度更快。
Lock锁同样可以完成代码同步的任务。
相较于synchronized方式,Lock锁的出现使同步操作更为灵活。无需使用限制性强的代码块。
Lock同样为抽象类,需要使用其子类ReentrantLock的对象完成方法调用。
主要方法:
public void lock()获取锁
public void unlock() 释放锁
2:线程死锁
在多线程的代码编辑过程中,由于考虑得不够周全,会出现死锁的情况。
线程死锁代码:备注
原因分析:
线程1将锁1锁住,线程2将锁2锁住,而线程1要继续执行锁2中的代码,线程2要继续执行锁1中的代码,但是此时,两个锁均处于锁死状态。最终导致两线程相互等待,进入无限等待状态。
有同步代码块的嵌套动作。
解决方法:
尽量不要写同步代码块嵌套
3:单例设计模式
内存当中只存在一个实例对象。
单例设计模式要求。
构造方法私有化
定义了自己类型的静态私有成员变量
对外提供公共的、静态的获取实例方法
实例创建方式分为懒汉式与饿汉式
懒汉式时,需要考虑线程安全问题
单例模式标准代码:
懒汉式:
class Single{
private static Single s = null;
private Single(){}
public static Single getIntance(){
if (s == null){
s = new Single();
}
return s;
}
}
饿汉式:
class Single{
private static Single s = new Single();
private Single(){}
public static Single getIntance(){
return s;
}
}