一、多线程安全问题产生原因
1、多个线程在操作共享的数据。
2、操作共享数据的代码有多条。
总之,多个线程同时执行操作共享数据的多行代码。
二、两种同步方法解决安全隐患
1、同步代码块解决安全隐患:
(1)解决思想:就是将多条操作共享数据的代码封装起来。当一个线程处理这些封装代码,其他线程不得参与运算,必须当前线程执行完之后,才可以执行其他的线程。
(2)同步代码块格式:
//所谓的对象锁,将这段代码锁住,同一时间,只有一个线程在处理。类似于火车的卫生间。。。。
synchronized(对象) //必须有一个对象
{
//需要同步代码,也就是多线程去处理的任务代码。
}
(3)同步的前提:
同步中必须有多个线程并且使用同一个对象锁。
(4)同步的弊端;
相对以前效率低,因为同步外的线程都会判断同步锁。(对象锁住后,其他线程也会取得执行权,并会不断判断同步锁的状态)。
2、同步函数解决安全隐患
(1)方法:直接在函数名前加上修饰符synchronized。
(2)同步函数的锁:就是this。
3、以上二者的区别
(1)同步函数和同步代码块区别:同步函数锁是固定this,同步代码块锁是任意的对象。
(2)静态同步函数的锁:该函数所属字节码文件对象,可以用this.getclass()方法获取,也可以用 类名.class 表示。
三、多线程死锁示例
1、产生的原因:同步锁的嵌套是导致死锁的原因之一。
2、死锁代码分析:自己写一个死锁代码。(证明你确实是懂死锁了)。
//死锁示例
public class DeadLock implements Runnable {
private boolean flag;
DeadLock(boolean flag) {
this.flag = flag;
}
public void run() {
if (flag) {
while (true) {
synchronized (Lockab.locka) {
System.out.println(Thread.currentThread().getName() + "--if--locka"); //如果一个线程在这里的时候,另外一个线程在下面的这个位置,就导致两个线程死锁。
synchronized (Lockab.lockb) {
System.out.println(Thread.currentThread().getName() + "--if--lockb");
}
}
}
} else {
while (true) {
synchronized (Lockab.lockb) {
System.out.println(Thread.currentThread().getName() + "--if--lockb");
synchronized (Lockab.locka) {
System.out.println(Thread.currentThread().getName() + "--if--locka");
}
}
}
}
}
}
class Lockab {
//两个对象锁
static final Object locka = new Object();
static final Object lockb = new Object();
}
class DeadTest {
public static void main(String[] args) {
//创建两个对象,分别用来执行true和false
DeadLock d1 = new DeadLock(true);
DeadLock d2 = new DeadLock(false);
//两个线程
Thread t1 = new Thread(d1);
Thread t2 = new Thread(d2);
t1.start();
t2.start();
}
}
分析:有两个锁a和b,线程0需要通过a锁、b锁去接触内容,线程1需要通过b锁、a锁去接触内容,但是如果线程0在a锁和b锁之间时、线程1在b锁和a锁之间时,就导致了死锁。因为线程0手里拿着a锁,线程1手里拿着b锁,互相不给、互相竞争。