线程的安全问题

一、线程的生命周期:

新建、就绪、运行、阻塞、死亡。如下图所示:

二、线程安全的出现和解决:

1.出现的原因:当一个线程操作某一个共享资源的时候,该操作尚未完成,其它线程参与进来,也去操作执行该资源,就会引发线程的安全问题。

2.解决办法:当一个线程操作的时候,其他线程不能参与进来,知道该线程操作完后,其他线程才能进行操作,这种情况即使是线程出现了阻塞,也不会被改变。

3.在java中,通过同步机制,来解决线程的安全问题。

  方式一:同步代码块

sychronized(同步监视器){
//需要被同步的代码
}

说明:操作共享数据的代码,就是需要被同步的代码

   共享数据:多个线程共同操作的变量。

扫描二维码关注公众号,回复: 6189297 查看本文章

   同步监视器:俗称:锁。任何一个类的对象,都可以充当锁。多个线程必须共用一把锁才能线程安全。

   同步解决了线程的安全,但是同时只能有一个线程参与,其他等待,相当于一个单线程,效率低。

  方式二:同步方法:

如果操作共享数据的代码完整的声明在一个方法中,这就是同步方法。

private sychronized void show(){//同步监视器:this
//需要被同步的代码
}
public void run(){
show();//调用线程安全的同步方法
}

注意:以上是在接口实现多线程的代码,在继承实现多线程的时候,this不是一个共有的,不能充当锁。这个时候就要加上静态或者用类来充当锁:

private  static sychronized void show(){//同步监视器:this
//需要被同步的代码
}

三、死锁和解决:

1.死锁:不同线程分别占用对方需要的同步资源不放弃,都在等待对方放弃自己需要的同步资源,就形成了线程的死锁。

出现死锁后,不会出现异常,不会有提示,只是所有的线程都处于阻塞状态,无法继续。

2.解决线程安全问题的方式三:lock锁——JDK5.0新增

private ReentrantLock lock = new ReentrantLock ();//实例化ReentrantLock 
lock.lock();//在需要同步的代码之前调用
lock.unlock();//同步结束后解除

3.synchronized和lock的异同?

相同:都是用来解决线程的安全问题

不同:sychronized机制在执行完相应的同步代码以后,自动的释放同步监视器,lock需要手动启动,同时结束同步后也需要手动实现。而且lock只有代码块锁,synchronize有代码块锁和方法锁。

 

四、线程的通信:

涉及到的三个方法:

1.  wait():一旦执行此方法,当前线程就进入阻塞状态,并释放同步监视器。

   notify():一旦执行此方法,就会唤醒被wait的一个线程。如果有多个线程被wait,就唤醒优先级高的。

   notifyAll():一旦执行此方法,就会唤醒所有被wait的线程。

2.注意:这三个方法必须使用在同步代码块或同步方法中。

      这三个方法的调用者必须是同步代码块或同步方法中的同步监视器。否则会出现IllegalMonitorStateException异常。

3.sleep()和wait()异同?

  相同:都可以使得当前线程进入阻塞状态。

  不同:①声明位置不同:Thread类中声明的sleep(),Object类中声明的wait()

     ②调用的要求不同:sleep()可以在任何需要的场景下调用。wait()必须在同步代码块或同步方法中。

     ③关于是否释放同步监视器:如果两个方法都使用在同步代码块或同步方法中,sleep()不会释放锁,wait()会释放锁。

猜你喜欢

转载自www.cnblogs.com/liuhuan425/p/10841730.html