线程安全、synchronized同步,Lock同步锁

  • 线程安全:数据共享时对数据读写出现错误(数据污染)。
  • 出现线程安全条件:

                                     a.多线程环境下,单线程无线程安全问题。

                                     b.数据共享发生,无数据共享无线程安全问题。

                                     c.对数据读写时,单一读无线程安全问题(数据共享),单一写存在线程问题。


 经典售票问题 


描述:现有100张(序号1-100)动物园门票出售。现有三个售票窗口进行售票。编写一个多线程程序模拟窗口售票。

分析:

  1. 三个窗口出售不同的票。没有什么问题,不存在数据共享不存在线程安全问题。

图片

   2.三个窗口同时出售100张票。这时候就会出现问题。数据共享读写出现线程问题。


Java编写程序:

按照分析第二条进行代码编写测试

代码
代码实现

 


运行程序控制台打印出现数据污染:

输出结果
部分结果

错误分析:先理解下线程调度的方式:线程的调度方式为抢占式,多个线程抢占资源,抢到资源处于运行状态,没抢到进入阻塞状态。运行线程释放资源,线程继续抢占。如此循环保证只有一个线程处于运行状态。因为线程调度和释放资源的速度很快所以感觉到多个线程同时在执行。

右下图分析可以看出:当一个线程执行到打印(读数据)时失去执行权,并没有对票数进行tiicket--操作,其他线程也进入运行状态这个时候就会出现多个窗口出售相同票的问题。执行到最后一张票时,可能还会出现线程执行减操作,其他线程进行读取时出现负数票情况。



线程安全解决方案

采用线程同步原理:使可能出现线程安全问题的代码始终只能有一个在执行,并且执行完毕后其他线程才能执行其中代码。

  1.  同步代码块:

                      synchronized(锁对象){

                            //可能出现线程安全的代码

                        }

代码
同步代码块

 

 

 

 

2.同步方法:

       对可能出现线程安全的代码使用同步方法

      修饰词 synchronized 返回值 方法名(参数){

                  //可能出现线程安全的代码

     }

图片
同步方法

 

3.使用Lock锁(java.util.concurrent.locks.Lock):

   a.创建锁对象(新建Lock接口的实现类  例如:Lock lock = new ReentrantLock(); )

图片
实现类所在包名     java.util.concurrent.locks.*

   b.在可能出现线程安全的代码获取锁

 

  c.在可能出现线程安全的代码释放锁

 

图片
Lock锁

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章