Java多线程同步机制研究分析

来源 :中国科教创新导刊 | 被引量 : 0次 | 上传用户:lujundehao
下载到本地 , 更方便阅读
声明 : 本文档内容版权归属内容提供方 , 如果您对本文有版权争议 , 可与客服联系进行内容授权或下架
论文部分内容阅读
  摘 要:Java多线程同步机制的应用有利于提高系统资源的利用率,改善系统的安全性。但是在多线程中最重要的问题是线程的同步和共享资源的访问保护。本文通过具有意义的售票系统的并发同步实例,对同步进行了探索。
  关键词:Java 多线程 同步
  中图分类号:G420 文献标识码:A 文章编号:1673-9795(2014)03(a)-0183-02
  至今,随着计算机技术的飞速发展和互联网的大面积普及,多处理器计算机已经司空见惯,在这种前景下,Java虚拟机(JVM)提供了一个多线程机制。在Java语言的编程设计中使用多线程运行机制来支持多任务和并行处理,可以让在同一地址空间中执行多控制流,显著的提高程序效率。但是线程的同步问题和共享资源的访问保护是非常复杂的问题。
  1 线程的同步机制
  多线程的应用程序中,两个或两个以上的线程可以共享同一片存储空间,这带来方便的同时,也导致线程共享资源发生冲突,此时我们可以使用Java语言提供的同步机制(又叫互斥锁机制)来解决此冲突问题。该同步机制是使用synchronized关键字控制一段程序代码,这代码段称为互斥区或临界区。定义临界区的目的是在任一时间只有一个线程使用共享资源,保证多线程的并发执行。Java语言的每个对象(即类实例)都对应一把锁(Lock),临界区使用锁来互斥多线程进入临界区。每次只有一个线程获得锁进入临界区,其它没有获得锁的线程必须在就绪队列中等待,直到该锁被释放。synchronized关键字的使用方式有synchronized方法和块两种。
  (1)synchronized方法:将访问共享资源的方法都标记为synchronized,然后该标记的方法来控制对类成员变量的访问。类实例和锁是一一对应的,当获得需要调用synchronized方法的类实例锁时,synchronized方法才可以执行,而且它开始执行直到完毕为止独占锁。这时其它调用synchronized方法的线程进入阻塞,一直到获得释放锁为止。定义同步方法语法格式如下:
  public synchronized void 方法名(参数列表){
  …//省略代码
  }
  (2)synchronized块:java语言中除了使用synchronized方法来设置同步,还可以使用synchronized块来设置同步。如果使用前者来修饰一个比较大的方法时,也会锁住了不需要锁住的字段,导致程序运行效率降低。后者是把程序的某段代码使用synchronized块来修饰,跟前者比它可以减少程序的同步区域。所以我们可以使用synchronized块来修饰语句块,能够弥补synchronized方法修饰的缺陷。定义同步块的语法格式如下:
  synchronized(表达式)//表达式的结果是当前对象{
  …//省略代码
  }
  从以上两种方法能够看出,关键字synchronized用来与对象的锁联系,当某个对象使用synchronized修饰时就意味着同步机制已启动,任一时刻只有让一个线程访问临界区资源,阻止其他线程访问该对象,即使出现阻塞和死锁现象,该对象的被锁定状态也不会解除。
  2 同步机制在售票系统的实现
  在现实生活当中也经常遇到多个线程共享同一个数据资源,典型的例子是火车票售票系统,来讲解线程共享资源。假设在售票厅内设10个售票窗口,每个售票窗口相当于一个线程,这些线程的共同访问资源为售票厅的100张票。若不设置同步机制代码如下:
  public class Ticket {
  public static void main(String[] args) {
  Sell_Ticket st = new Sell_Ticket();//创建10个线程,每个线程代表一个售票口
  for (int i = 0; i < 10; i++) new Thread(st, "第" + i + "个窗口").start();
  }
  }
  class Sell_Ticket implements Runnable {
  int trainTicket = 100;//预售的票数
  boolean flag = false;//循环控制标志
  public void run(){
  while (!flag) {// 当还有剩余票时继续售票
  sellTicket(); }
  }
  public void sellTicket(){
  if (trainTicket > 0) {
  System.out.println(Thread.currentThread().getName()+ "售票成功,剩余票数:"
  + trainTicket);
  trainTicket--;
  } else flag = true;
  }
  }
  運行的结果是多个窗口同时售票,会出现剩余票数变为负数的情况,即10个线程从100张票卖到1张票的时候还没有停止卖,系统出现继续卖出负数票的现象。
  下面通过Java的多线程同步机制的synchronized方法和块两种方式来分别解决以上出现的问题。为了便于观察到运行错误,特意添加Thread.sleep(10)方法,让每个线程在售票阶段睡眠10 ms。
  (1)使用synchronized方法:在售票方法sellTicket()的前面添加synchronized关键字,就相当于使用一把锁锁住该方法。修改后的程序代码如下:   public synchronized void sellTicket(){
  if (trainTicket > 0) {
  try {
  Thread.sleep(10);//睡眠10毫秒
  } catch (InterruptedException e) {e.printStackTrace();}
  System.out.println(Thread.currentThread().getName()+ "售票成功,剩余票数:"+ trainTicket);
  trainTicket--;
  } else flag = true;
  }
  以上是使用synchronized关键字修饰sellTicket()方法,对该方法实现了多线程的互斥访问。程序运行run()方法以后,当判断出还有剩余票时调用被加锁的sellTicket()方法,这时的sellTicket()方法,在同一个时间段内只能被一个线程访问。
  若synchronized关键字修饰静态方法sellTicket(),锁住的就是类本身。因为静态方法是所有类实例对象所共享的,因此线程对象在访问此静态方法时是互斥访问的,从而可以实现线程的同步。实现方法如下所示:
  public static synchronized void sellTicket() {}
  (2)使用synchronized块:在程序中的if语句外面加synchronized关键字,就相当于使用一把锁锁住了这段代码。它不同于同步方法,传递一个对象进行同步。修改后的程序如下:
  Object object =new Object();
  public void run() {
  while (!flag) { // 当还有剩余票时继续售票
  synchronized(object){
  if (trainTicket > 0) {
  try {
  Thread.sleep(10);
  } catch (InterruptedException e) {e.printStackTrace();}
  System.out.println(Thread.currentThread().getName()+ "售票成功,剩余票数:"
  + trainTicket);
  trainTicket--;
  } else flag = true;
  }
  }
  }
  以上是使用synchronized关键字修饰了售票代码段,对该代码段实现了多线程的互斥访问。同步块不像同步方法修饰整个方法,而修饰一段代码即可。synchronized(object)传递的是一个对象object,如果多线程想使用该对象的方法和变量,首先判断有没有加锁,若已加锁,等待锁的释放;若没有锁,先将给它加锁,然后去执行代码。在同一个时间段内只能有一个线程能够获得这把锁。
  同步块的关键是多个线程对象竞争同一个共享资源即可,上面的代码中是通过外部创建共享资源,然后传递到线程中来实现。我们也可以利用类成员变量被所有类的实例所共享这一特性,因此可以将object对象用静态成员对象来实现,如下所示:
  static Object object =new Object();
  使用synchronized方法和块两种方式修改后的运行结果相同,剩余票数每次减1,从100减到0,到0时flag=true,while循环结束,即不能售票。
  3 结语
  Java程序中通过synchronized關键字来实现互斥访问。本文引用的售票系统,通过synchronized方法和块两种方式实现了线程的同步互斥,避免了车票售完以后还能继续售票导致数据混乱的问题。总之,合理使用多线程同步机制才能让数据资源得到安全保障。
  参考文献
  [1] 明日科技.Java从入门到精通[M].3版.北京:清华大学出版社,2013.
  [2] 沈祥玖,李作纬.操作系统原理与应用[M].3版.北京:高等教育出版社,2013.
  [3] 路勇.Java多线程同步问题分析[J].软件,2012(4):31-33.
其他文献
美国女作家项美丽的传记作品《宋氏三姐妹》,生动地塑造了三姐妹的父亲宋查理的形象。在其他传记文本中,宋查理具有明显的中国文化身份,而在这部作品中,宋查理形象很大程度上被简
随着信息技术的不断发展,从独立平台到综合系统集成,从单一服务到业务融合,实现统一框架中的纵向、横向管理,是电信行业IT系统架构发展规律。系统整合的一个重要基础是用户账
PM2.5污染已成为我国突出的大气环境问题,开展PM2.5科普以减少PM2.5污染带来的危害已成为科普工作的新热点.通过对合肥市公民PM2.5科学素养的问卷调查,了解到该地区市民对于P
摘 要:对口升学从20世纪90年代中期就已经开始,在本地区是在1997年开始汽驾类对口升学考试的,我校汽修专业教师能够编写学校教学大纲和编写练习题,抓住复习重点,结合学生现状,采取科学实用的复习策略,取得了可喜的成绩。  关键词:对口升学 复习方法 成绩  中图分类号:G421 文献标识码:A 文章编号:1673-9795(2013)03(b)-0138-01  20世纪90年代中期,随着国家经济
摘 要:新课程改革要求教师要有效整合课堂教学资源,合理调整课堂结构,更好贯彻新课程教学原则,凸显学生学习主体地位,搞好双边教学。特别要对学生心理变化进行调查研究,找到解决问题切入点,建立和谐课堂,构建合作学习模式,实现最佳教学效果。中学语文课堂教学学生心理探究实践对促进课堂教学成功转型有重要意义。  关键词:新课程 语文 课堂教学 学生心理 变化 对策  中图分类号:G63 文献标识码:A 文章编
梅贻琦的大学体育思想是其教育思想的重要组成部分。关于大学体育的价值、目的、内容及管理,梅贻琦提出了“乐事体育”、“体育是培养高尚人格最好的方法”、“体育救国”等体
本文探索了“PBL-PEL-LBL”教学模式在生理学教学中的步骤和效果.方法;根据创建生理学的过程和规律,重新安排并整合教学大纲内容,合理运用PBL、PEL与LBL三种教学方法.结果表
严如煜之所以能够彪炳史册,名垂千古,与其求学于湖湘文化的中心长沙岳麓书院密切相关。严如煜在岳麓书院的最大收获是对经世致用思想的认同与提倡。严如煜离开岳麓书院之后,不论
当代几乎所有的解放运动都是在社会主义的旗帜下进行的,这无疑是现时国际生活中最重要的因素。然而,选择什么样的道路来实现社会主义社会,如何建设它,对这些问题,人们在认识上显然
煤炭深加工项目属技术密集、资金密集型产业,由于我国煤炭和水资源呈逆向分布,并且煤炭资源种类繁多,深加工项目前期工作面临多种选择,工作难度大。结合工作实践,本文就煤炭深加工