一.Java多线程模型
在Java中,每个线程用一个Thread对象表示,每个线程有自己的执行流即方法调用栈和程序计数器。通过对Thread对象执行start操作,会让线程开始执行Thread的run方法,而run方法则是线程的执行流。
可以采用thread.sleep(),thread.interrupt(),thread.join()来控制单个线程的执行流。
二.Java多线程如何解决互斥和协同的问题
对于互斥问题,Java提供了锁机制,即synchronized关键字。另外对于单个变量的读写,java提供了volatile关键字,确保对单个变量的读和写是原子操作,即保证读和写是完整的,不会出错。
对于协同问题,Java提供了信号操作,即object的wait()和notify(),notifyAll()方法,即等待和唤醒策略。
三.Java多线程的其他问题
值得注意的就是可见性问题,由于java虚拟机里的内存模型是,每个线程有自己的一块工作空间,以方便加快程序的执行速度,这些工作空间里存储的是堆空间里的数据的缓存。由于每个线程都有自己对共享变量的一份缓存,从而导致出现共享变量的一致性问题。比如线程A对一个变量自增一,线程B也对一个变量自增一,如果两个线程并发的运行,除了确保每次只能有一个线程读取变量,修改变量,还必须确保,线程对这个变量进行的读和写是同步到公共的内存空间里去了。
对于共享变量的读和写的一致性问题,需要依赖对读和写操作确定happen-before关系来解决。就是如果要使一个写操作对其他线程的读操作可见,那么写操作的结果需要在读操作之前保存到共享空间中,并且读操作需要从共享空间中读取变量,不能采用自己工作空间的缓存。
如果对共享变量的操作没有happen-before关系,那么默认是不保证读操作能读到其他线程写的数据的。
Java规定的happen-before关系的操作
Each action in a thread happens-before every action in that thread that comes later in the program's order.
An unlock (synchronized block or method exit) of a monitor happens-before every subsequent lock (synchronized block or method entry) of that same monitor. And because the happens-before relation is transitive, all actions of a thread prior to unlocking happen-before all actions subsequent to any thread locking that monitor.
A write to a volatile field happens-before every subsequent read of that same field. Writes and reads of volatile fields have similar memory consistency effects as entering and exiting monitors, but do not entail mutual exclusion locking.
A call to start on a thread happens-before any action in the started thread.
All actions in a thread happen-before any other thread successfully returns from a join on that thread.
高级同步方案中的happen-before关系
Actions in a thread prior to placing an object into any concurrent collection happen-before actions subsequent to the access or removal of that element from the collection in another thread.
Actions in a thread prior to the submission of a Runnable to an Executor happen-before its execution begins. Similarly for Callables submitted to an ExecutorService.
Actions taken by the asynchronous computation represented by a Future happen-before actions subsequent to the retrieval of the result via Future.get() in another thread.
Actions prior to "releasing" synchronizer methods such as Lock.unlock, Semaphore.release, and CountDownLatch.countDown happen-before actions subsequent to a successful "acquiring" method such asLock.lock, Semaphore.acquire, Condition.await, and CountDownLatch.await on the same synchronizer object in another thread.
For each pair of threads that successfully exchange objects via an Exchanger, actions prior to the exchange() in each thread happen-before those subsequent to the corresponding exchange() in another thread.
Actions prior to calling CyclicBarrier.await and Phaser.awaitAdvance (as well as its variants) happen-before actions performed by the barrier action, and actions performed by the barrier action happen-beforeactions subsequent to a successful return from the corresponding await in other threads.
四.Java多线程提供的高级解决方案有哪些
Lock,代替synchronized,wait,notify,notifyall
原子操作类AtomicInteger,AtomicLong,原理是非阻塞锁,实现单个对象的原子操作。
同步容器类ConcurrentHashMap,BlockedQueue,CopyOnWriteArray,对容器的元素操作进行锁操作。
线程控制框架Excuter,ExcuterService,ScheduleExcuterService提供线程池,线程创建功能。
五.Java多线程的指令重排序问题
指令重排问题:其实不用太过于担心,因为java在单个线程内部是不可能随便将指令进行乱序执行的,因为首先它要保证排序后的结果和代码的正常执行流程是一样的。比如先有一个system.out.println(1);再有一个system.out.println(2);在单个线程中,结果一定是先输出1再输出2,不会是先2后1。想想,如果这都不能操作,那我们还能信任编译器吗?所以jvm只敢在那些不影响程序外部表现的地方进行指令重排,而且需要保证不出错,如果真出错了,这个概率较小,计算机本身都有可能出错。
其实关注指令重排问题,是由于之前深入java虚拟机中,举的例子,说多线程操作共享变量,然后结果不一。原因很简单,在线程内部结果是一致的。只是涉及到了其他线程的时候,如果不对共享变量进行同步,会有两个问题,一个是可见性问题,二个是指令重排。而且java中提供的synchronized,volitale,ReentrantLock等锁的机制已经确保可见性和指令重排不会造成影响,所以不用考虑指令重排,只要考虑可见性即可。指令重排不需要我们知道,它本来就是jvm自己内部自己优化的东西,如果指令重排后程序出错了,这个是编译器的问题,我想它不太可能出这样的问题。
所以不用看指令重排了,搞定可见性就可以了。
可以参看java的官网上关于同步的教程,指令重排的问题根本没有提及,只提到了可见性,如果指令重排会导致程序出错,不合常理。
附录:
一.Thread的6种状态
l NEW
Thread state for a thread which has not yet started.
l RUNNABLE
Thread state for a runnable thread. A thread in the runnable state is executing in the Java virtual machine but it may be waiting for other resources from the operating system such as processor.
l WAITING
Thread state for a waiting thread. A thread is in the waiting state due to calling one of the following methods:
Object.wait with no timeout
Thread.join with no timeout
A thread in the waiting state is waiting for another thread to perform a particular action. For example, a thread that has called Object.wait() on an object is waiting for another thread to call Object.notify() or Object.notifyAll() on that object. A thread that has called Thread.join() is waiting for a specified thread to terminate.
l BLOCKED
Thread state for a thread blocked waiting for a monitor lock. A thread in the blocked state is waiting for a monitor lock to enter a synchronized block/method or reenter a synchronized block/method after calling Object.wait
.
l TIME-WAITING
Thread state for a waiting thread with a specified waiting time. A thread is in the timed waiting state due to calling one of the following methods with a specified positive waiting time:
- Thread.sleep
- Object.wait with timeout
- Thread.join with timeout
- LockSupport.parkNanos
- LockSupport.parkUntil
l TERNINATED
Thread state for a terminated thread. The thread has completed execution.
二. 重要参考资料
java官方多线程教程:http://docs.oracle.com/javase/tutorial/essential/concurrency/index.html
java7的api文档:http://docs.oracle.com/javase/7/docs/api/
相关推荐
Java支持原生多线程编程,这意味着开发者可以直接在Java程序中创建多个线程并发执行任务,这对于提高程序性能非常关键。 **5. 分布性** Java支持分布式计算环境,使得开发者能够轻松地构建分布式应用程序。通过...
根据给定的信息,“数学概观(PDF)”这一标题表明文档是关于数学整体的一个概述,旨在为读者提供一个全面的视角来理解数学这门学科。虽然提供的部分内容并未包含实际的数学知识,但从标题和描述来看,我们可以推断...
王森的Java深度历险 本书特色有:说明JDK,JRE与JVM三者的关系:探讨Java应用程序的执行流程,让您以后不会再为JDK与JRE的版本问题苦恼;讲解类别载入器的运作机制:类别载入器兼具Java程序的...Java 2 SDK源代码概观。
多线程是Java的重要特性,它使得程序能够同时执行多个任务。学习如何创建和管理线程,理解同步机制(如synchronized关键字、Lock接口)以及并发工具(如Semaphore、CountDownLatch),是成为高级Java开发者的必备...
WiFi概观360专业版是一款专业的wifi基本数据分析应用,可以帮助用户检测,分析不同的wifi的各种信息,包括强度、速度等等,帮助你选择最好的wifi进行链接,是一款非常不错的wifi工具软件, 主要功能: - WiFi 探 测...
书中还涵盖了Java 2 Software Development Kit (SDK)的原始码概观。通过理解SDK的源代码,开发者可以深入理解JVM的工作方式,包括类加载、内存管理、异常处理等核心机制,这对于优化代码性能和排查问题具有极大价值...
Java深度历险 深入Java 2 SDK 深入类别载入器 Java与MS Office 用Visual Studio.net操控Java虚拟机 package与import机制 Ant 附录A.Java 2 SDK原版码概观
深入Java 2 SDK.pdf** - 这一章深入探讨了Java 2 SDK,可能包括JVM的运行机制,核心类库的使用,以及一些高级特性,如多线程、网络编程、异常处理等。 8. **CH_05.package与import机制.pdf** - Java的包(package)和...
本书特色有:说明JDK,JRE与JVM三者的关系:探讨Java应用程序的执行流程,让您以后不会再为JDK与JRE的版本问题苦恼;讲解类别载入器的运作机制:类别载入器兼具Java程序的弹性与安全性两项...Java 2 SDK源代码概观。
`附录A.Java 2 SDK版原始码概观.pdf`可能提供了Java 2 SDK源码的概述,这对于理解ClassLoader的工作方式非常有帮助,因为你可以看到其内部的实现细节。 `CH_00-导读.pdf`则可能是整个系列的引导章节,介绍了接下来...
7年来,Java已发展得非常成熟,市面上有太多介绍Java程序语言与Java各种应用的好书。Java在企业端(Enterprise)与嵌入式系统(Embedded System,手机与PDA等)上扮演举足轻重的角色。而这些出色的应用,都是因为...
概观C++程序设计语言.chm 概观C++程序设计语言.chm
概观C++程序设计语言
《2022年最新中华传统文化概观形成性考核册》中的论述题涉及到中华传统文化的多个重要方面,其中特别提到了孟子的哲学思想及其对儒家文化的影响,以及中国古代“家国同构”的政治结构。 孟子,作为儒家学派的重要...