`
pda158
  • 浏览: 192777 次
社区版块
存档分类
最新评论

Java线程同步如何才能排除阻塞

阅读更多

Java线程同步需要我们不断的进行相关知识的学习,下面我们就来看看如何才能更好的在学习中掌握相关的知识讯息,来完善我们自身的编写手段。希望大家有所收获。

  Java线程同步的优先级代表该线程的重要程度,当有多个线程同时处于可执行状态并等待获得 CPU 时间时,线程调度系统根据各个线程的优先级来决定给谁分配 CPU 时间,优先级高的线程有更大的机会获得 CPU 时间,优先级低的线程也不是没有机会,只是机会要小一些罢了。

  你可以调用 Thread 类的方法 getPriority() 和 setPriority()来存取Java线程同步的优先级,线程的优先级界于1(MIN_PRIORITY)和10(MAX_PRIORITY)之间,缺省是5(NORM_PRIORITY)。

  Java线程同步

  由于同一进程的多个线程共享同一片存储空间,在带来方便的同时,也带来了访问冲突这个严重的问题。Java语言提供了专门机制以解决这种冲突,有效避免了同一个数据对象被多个线程同时访问。

  由于我们可以通过 private 关键字来保证数据对象只能被方法访问,所以我们只需针对方法提出一套机制,这套机制就是 synchronized 关键字,它包括两种用法:synchronized 方法和 synchronized 块。

  1. synchronized 方法:通过在方法声明中加入 synchronized关键字来声明 synchronized 方法。如:

 

public synchronized void accessVal(int newVal);

 

  synchronized 方法控制对类成员变量的访问:每个类实例对应一把锁,每个 synchronized 方法都必须获得调用该方法的类实例 的锁方能执行,否则所属线程阻塞,方法一旦执行,就独占该锁,直到从该方法返回时才将锁释放,此后被阻塞的Java线程同步方能获得该锁,重新进入可执行状态。

  这种机制确保了同一时刻对于每一个类实例,其所有声明为 synchronized 的成员函数中至多只有一个处于可执行状态(因为至多只有一个能够获 得该类实例对应的锁),从而有效避免了类成员变量的访问冲突(只要所有可能访问类成员变量的方法均被声明为 synchronized)。

  在 Java 中,不光是类实例,每一个类也对应一把锁,这样我们也可将类的静态成员函数声明为 synchronized ,以控制其对类的静态成员变量的访问。

  synchronized 方法的缺陷:若将一个大的方法声明为synchronized 将会大大影响效率,典型地,若将线程类的方 法 run() 声明为 synchronized ,由于在线程的整个生命期内它一直在运行,因此将导致它对本类任何 synchronized 方法 的调用都永远不会成功。当然我们可以通过将访问类成员变量的代码放到专门的方法中,将其声明为 synchronized ,并在主方法中调用来解决这一 问题,但是 Java 为我们提供了更好的解决办法,那就是 synchronized 块。

  2. synchronized 块:通过 synchronized关键字来声明synchronized 块。语法如下:

 

  • synchronized(syncObject)  
  • {  
  • //允许访问控制的代码  
  • }

 

  synchronized 块是这样一个代码块,其中的代码必须获得对象 syncObject (如前所述,可以是类实例或类)的锁方能执行,具体机制同前所述。由于可以针对任意代码块,且可任意指定上锁的对象,故灵活性较高。

Java线程同步的阻塞

  为了解决对共享存储区的访问冲突,Java 引入了同步机制,现在让我们来考察多个Java线程同步对共享资源的访问,显然同步机制已经不够了,因为在任意时刻所要 求的资源不一定已经准备好了被访问,反过来,同一时刻准备好了的资源也可能不止一个。为了解决这种情况下的访问控制问题,Java 引入了对阻塞机制的支 持。

  阻塞指的是暂停一个Java线程同步的执行以等待某个条件发生(如某资源就绪),学过操作系统的同学对它一定已经很熟悉了。Java 提供了大量方法来支持阻塞,下面让我们逐一分析。

  1. sleep() 方法:sleep() 允许指定以毫秒为单位的一段时间作为参数,它使得线程在指定的时间内进入阻塞状态,不能得到CPU 时 间,指定的时间一过,线程重新进入可执行状态。典型地,sleep() 被用在等待某个资源就绪的情形:测试发现条件不满足后,让线程阻塞一段时间后重新 测试,直到条件满足为止。

  2. suspend() 和 resume() 方法:两个方法配套使用,suspend()使得线程进 入阻塞状态,并且不会自动恢复,必须其对应的resume() 被调用,才能使得线程重新进入可执行状态。典型 地,suspend() 和 resume() 被用在等待另一个线程产生的结果的情形:测试发现结果还没有产生后,让线程阻塞,另一个线程产生了结果 后,调用 resume() 使其恢复。

  3. yield() 方法:yield() 使得线程放弃当前分得的 CPU 时间,但是不使线程阻塞,即线程仍处于可执行状态,随时可能再次分得 CPU 时间。调用 yield() 的效果等价于调度程序认为该Java线程同步已执行了足够的时间从而转到另一个线程。

  4. wait() 和 notify() 方法:两个方法配套使用,wait() 使得线程进入阻塞状态,它有两种形式,一种允许指定以毫秒为单位的 一段时间作为参数,另一种没有参数,前者当对应的 notify() 被调用或者超出指定时间时Java线程同步重新进入可执行状态,后者则必须对应 的 notify() 被调用。

  初看起来它们与 suspend() 和 resume() 方法对没有什么分别,但是事实上它们是截然不同的。区别的核心在于,前面叙述的所有方法,阻塞时都不会释放占用的锁(如果占用了的话),而这一对方法则相反。

4
0
分享到:
评论

相关推荐

    Java问题定位技术.pdf

    它详细介绍了如何通过Java线程堆栈分析来诊断和解决Java应用程序中的各种问题。文档从线程堆栈的输出和解读方法开始,逐步深入到具体的性能问题分析,包括线程死锁、CPU过度使用、性能瓶颈、内存泄漏等方面。 首先...

    IBM Thread and Monitor Dump Analyzer for Java

    1. **线程分析**:列出所有活动线程的状态,如运行、等待、阻塞等,并给出详细的状态信息,如持有锁、等待锁等。 2. **锁分析**:显示哪些线程持有特定的锁,以及哪些线程正在等待这些锁,帮助定位死锁问题。 3. *...

    JAVA笔记JAVA笔记.docx

    - 线程同步机制主要包括`synchronized`关键字和显式锁机制。 - 死锁是指两个或多个线程永久阻塞,因为每个线程都在等待其他线程释放资源。 - **生产者-消费者问题**: - 这是一个经典的多线程问题,通常通过共享...

    java面试2016

    线程的状态包括新建、就绪、运行、阻塞和死亡。状态之间可以相互转换。 #### 54. `synchronized`与`java.util.concurrent`包 - `synchronized`:基于锁的同步机制。 - `java.util.concurrent`包提供了更高级的并发...

    2009年9月全国计算机等级考试二级Java笔试试题及答案.pdf

    18. 多线程同步:在Java的多线程程序中,两个线程共享变量并同时修改可能导致结果不可预测,但每一对(x, y)值只会出现一次,选择题(18)的B选项是正确的描述。 19. 线程状态:运行状态的线程可能进入阻塞、可运行...

    Java经典面试题+答案(带书签)pdf

    - 必须确保所有访问共享资源的线程都通过相同的锁进行同步。 **10. 线程的优先级** - 线程的优先级用于指示调度器应如何调度线程。 - Java中线程的优先级范围通常是1到10。 **11. 线程获取名称** - 线程名称可以...

    websphere cpu性能问题

    总的来说,解决Websphere的CPU性能问题需要综合运用多种技术,包括操作系统级别的监控、Java线程分析和应用程序代码审查。通过系统的故障排除,通常可以定位到问题的根源,从而制定出有效的优化策略,降低CPU占用率...

    用java中的jpanel实现的扫雷小游戏.zip

    扫雷游戏通常需要在用户交互和游戏逻辑之间进行同步,这可能涉及使用多线程技术,确保游戏状态的更新不会阻塞用户界面的响应。 5. **二维数组存储游戏状态**: 开发者可能会用一个二维数组来表示游戏区域,每个...

    公司年会抽奖系统

    同时,线程间的同步也是重要的一环,比如使用`synchronized`关键字或`Lock`接口来防止多个线程同时进行抽奖,保证抽奖的公平性。 再者,随机数生成是抽奖系统的核心算法之一。Java提供了`Random`类用于生成随机数,...

    cyanogenmod-android_packages_java_android_

    **网络请求与数据同步**:为了获取专辑封面,应用可能使用了HttpURLConnection、OkHttp等网络库发起HTTP请求,或者集成Retrofit、Volley等现代网络库,同时可能结合AsyncTask或Coroutines处理异步任务,避免阻塞UI...

    经典的问题

    - 如果多个线程访问未同步的共享资源,可能会导致竞态条件和不一致状态。 **10. 线程的优先级** - 线程的优先级决定了CPU时间片的分配顺序,但并不保证一定会按照优先级执行。 **11. 线程获取名称** - 线程名称...

    unity3d逻辑程序员开发面试题.doc

    C#线程则是多线程处理,可能涉及到线程同步和线程安全问题,处理复杂异步任务时更强大,但管理起来也更复杂。 面试题八:如何让物体A朝向物体B? 可以使用Transform.LookAt()函数,让A物体面向B物体的方向。注意...

    Java RMI的企业级应用及框架设计 (2007年)

    例如,当客户端调用服务器端的私有对象时,可能会因其他方法在处理过程中发生意外阻塞而导致RMI连接线程进入非正常状态,且基础的RMI服务器并没有机制对此做出处理,无法自动终止问题线程。这一问题可能发生的频率不...

    Learning Concurrent Programming in Scala

    接着,作者转向JVM和Java内存模型,讨论了进程和线程的概念、创建和启动线程的机制、原子执行和指令重排序的问题、监视器与同步机制、死锁、守护块以及线程中断和优雅的关闭机制。此外,书中也探讨了Java内存模型和...

    安卓飞机大战

    在这个项目中,源码可能是用Java编写的,因为早期的Android开发主要使用Java,但也不排除使用Kotlin的可能性,因为Kotlin现在已经成为Android开发的首选语言。开发者需要熟悉这两种语言的语法和特性,以及如何在...

    基于xxxxxx系统_用户手册.docx.zip

    6. **多线程**:线程的创建、同步、通信和状态管理。 7. **网络编程**:Socket编程,HTTP、HTTPS协议的实现。 8. **反射与注解**:运行时动态类信息获取,以及注解的使用场景和自定义注解。 9. **设计模式**:常见的...

Global site tag (gtag.js) - Google Analytics