当前位置:文档之家› 多线程同步机制

多线程同步机制

操作系统用来管理进程的内核对象
内核对象也是系统用来存放进程统计信息的地方, 内核对象的数据结构只能被内核访问和使用,应用 程序在内存中无法找到该数据结构,并直接改变其 内容,只能通过Windows提供的一些API来对内核对 内容,只能通过Windows提供的一些API来对内核对 象进行操作
地址空间
包含所有可执行模块或DLL模块的代码和数据,也 包含所有可执行模块或DLL模块的代码和数据,也 包含动态内存分配的空间。
Java多线程协作( Java多线程协作(续) 多线程协作
示例:
有一家汉堡店举办吃汉堡比赛,决赛时有3 有一家汉堡店举办吃汉堡比赛,决赛时有3个顾客来吃, 3个厨师来做,一个服务员负责协调汉堡的数量。为了 避免浪费,制作好的汉堡被放进一个能装有10个汉堡的 避免浪费,制作好的汉堡被放进一个能装有10个汉堡的 长条状容器中,按照先进先出的原则取汉堡。如果容 器被装满,则厨师停止做汉堡,如果顾客发现容器内 的汉堡吃完了,就可以拍响容器上的闹铃,提醒厨师 再做几个汉堡出来。此时服务员过来安抚顾客,让他 等待。而一旦厨师的汉堡做出来,就会让服务员通知 顾客,汉堡做好了,让顾客继续过来取汉堡。 顾客其实就是我们所说的消费者,而厨师就是生产者。 容器是决定厨师行为的监视器(在JVM中,此种监视器 容器是决定厨师行为的监视器(在JVM中,此种监视器 被称为等待并唤醒监视器。 ),而服务员则负责监视 顾客的行为。
多线程同步机制
--------- 李晓慧
目录
概念 为什么要同步 ? Java中是如何实现多线程同步的? Java中是如何实现多线程同步的? VC中是如何实现多线程同步的? VC中是如何实现多线程同步的?
概念
进程 线程 进程和线程的关系 多线程
ቤተ መጻሕፍቲ ባይዱ程
是应用程序的执行实例,每个进程是由私 有的虚拟地址空间、代码、数据和其它各 种系统资源组成 组成部分
为了解决synchronized 块存在的问题,JDK 5中新引入了 为了解决synchronized 块存在的问题,JDK 5中新引入了 并发框架中的锁机制。 java.util.concurrent.lock 中的 Lock 框架是锁定的一个抽象,它允许把锁定的实现作 为 Java 类,而不是作为语言的特性来实现 ReentrantLock是 ReentrantLock是“一个可重入的互斥锁 Lock,它具有 Lock,它具有 与使用 synchronized 方法和语句所访问的隐式监视器锁 相同的一些基本行为和语义,但功能更强大。
Java中锁的概念( Java中锁的概念(续) 中锁的概念
类锁实际上用对象锁来实现。当虚拟机装载一个class文件 类锁实际上用对象锁来实现。当虚拟机装载一个class文件 的时候,它就会创建一个ng.Class类的实例。当锁住 的时候,它就会创建一个ng.Class类的实例。当锁住 一个对象的时候,实际上锁住的是那个类的Class对象。 一个对象的时候,实际上锁住的是那个类的Class对象。 一个线程可以多次对同一个对象上锁。对于每一个对象, java虚拟机维护一个加锁计数器,线程每获得一次该对象, java虚拟机维护一个加锁计数器,线程每获得一次该对象, 计数器就加1 计数器就加1,每释放一次,计数器就减 1,当计数器值为 0时,锁就被完全释放了。 java编程人员不需要自己动手加锁,对象锁是java虚拟机内 java编程人员不需要自己动手加锁,对象锁是java虚拟机内 部使用的。 在java程序中,只需要使用synchronized块或者synchronized java程序中,只需要使用synchronized块或者synchronized 方法就可以标志一个监视区域。当每次进入一个监视区域 时,java 时,java 虚拟机都会自动锁上对象或者类。
HambergShop
ThreadLocal
不论是同步还是重入锁,都不能实实在在的解决资源紧缺 的情况,这些方案只是靠制定规则来约束线程的行为,让 它们不再拼命的争抢,而不是真正从实质上解决他们对资 源的需求。 在JDK 1.2当中,引入了ng.ThreadLocal它为我们提供 1.2当中,引入了ng.ThreadLocal它为我们提供 了一种全新的思路来解决线程并发的问题,ThreadLocal其 了一种全新的思路来解决线程并发的问题,ThreadLocal其 实是源于一项多线程技术,叫做Thread 实是源于一项多线程技术,叫做Thread Local Storage,即 Storage,即 线程本地存储技术。 当使用ThreadLocal维护变量时,它会为每个使用该变量的 当使用ThreadLocal维护变量时,它会为每个使用该变量的 线程提供独立的变量副本,它是从根本上解决资源数量的 问题,从而使得每个线程持有相对独立的资源。这样,当 多个线程进行工作的时候,它们不需要纠结于同步的问题, 于是性能大大提升。但资源的扩张带来的是更多的空间消 耗,ThreadLocal就是一种利用空间来换取时间的解决方案。 耗,ThreadLocal就是一种利用空间来换取时间的解决方案。
线程
是进程内部的一个执行单元。系统创建好 进程后,实际上就启动执行了该进程的主 执行线程,主执行线程终止了,进程也就 随之终止。 组成部分
线程的内核对象
操作系统用它来对线程实施管理,也是系统用来存 放线程统计信息的地方
线程栈
用于维护线程在执行代码时需要的所有函数参数和 局部变量
进程和线程的关系
真正完成代码执行的是线程,而进程只是 线程的容器,或者说是线程的执行环境。 一个进程可以包含若干个线程,这些线程 都“同时”执行进程地址空间中的代码 同时” 一个进程至少拥有一个线程来执行其地址 空间中的代码,创建进程时系统会自动创 建这个进程的第一个线程,称为“ 建这个进程的第一个线程,称为“主线 程”。 线程总是在某个进程环境中创建,系统从 进程的地址空间中分配内存供线程的栈使 用。
Lock 锁(续)
Lock锁的优势: Lock锁的优势:
对象锁的获得和释放是由手工编码完成的,所以获得锁和释放锁 的时机比使用同步块具有更好的可定制性。并且通过程序的运行 结果(运行结果忽略,请读者根据例程自行观察),我们可以发 现,和使用同步块的版本相比,结果是相同的。 ReentrantLock 类(重入锁)实现了 Lock ,它拥有与 synchronized 相同的并发性和内存语义,但是添加了类似锁投票、定时锁等候 和可中断锁等候的一些特性。此外,它还提供了在激烈争用情况 下更佳的性能。(换句话说,当许多线程都想访问共享资源时, JVM 可以花更少的时候来调度线程,把更多时间用在执行线程 上。) 使用新的ReentrantLock,免去了为同步块放置合适的对象锁所要 使用新的ReentrantLock,免去了为同步块放置合适的对象锁所要 进行的考量 使用新的ReentrantLock,最佳的实践就是结合try/finally块来进行。 使用新的ReentrantLock,最佳的实践就是结合try/finally块来进行。 在try块之前使用lock方法,而在finally中使用unlock方法。 try块之前使用lock方法,而在finally中使用unlock方法。
对象锁
在Java多线程编程中,最常见的synchronized关键 Java多线程编程中,最常见的synchronized关键 字实际上是依靠对象锁的机制来实现线程同步的。 同步有两种方式,同步块和同步方法。 同步方法
则分静态和非静态两种 ,静态方法则一定会同步,非 静态方法需在同一个实例时才生效 对象锁即为method所在的对象,如果是静态方法,对 对象锁即为method所在的对象,如果是静态方法,对 象锁即指method所在的Class对象(唯一); 象锁即指method所在的Class对象(唯一);
synchronized块的限制: synchronized块的限制:
它无法中断一个正在等候获得锁的线程,也无法通过投票得到 锁,如果不想等下去,也就没法得到锁。 synchronized 块对于锁的获得和释放是在相同的堆栈帧中进行 的。多数情况下,这没问题(而且与异常处理交互得很好), 但是,确实存在一些更适合使用非块结构锁定的情况。
为什么要同步? 为什么要同步?
问题:
多个线程竞争同一个资源 资源紧缺 多线程协作
解决方法:
保证对共享资源的互斥访问 保证线程的先来后到 制定一个规则来约束线程的行为
Java中是如何实现多线程同步的? Java中是如何实现多线程同步的? 中是如何实现多线程同步的 Java中锁的概念 Java中锁的概念 对象锁 Lock锁 Lock锁 Java多线程协作 Java多线程协作 ThreadLocal
Java多线程协作( Java多线程协作(续) 多线程协作
当线程在调用某个对象的wait或者notify方法的时 当线程在调用某个对象的wait或者notify方法的时 候,要先取得该对象的控制权,换句话说,就是 进入这个对象的监视器,因为:
任何一个时刻,对象的控制权只能被一个线程拥有。 无论是执行对象的wait、notify还是notifyAll方法,必须 无论是执行对象的wait、notify还是notifyAll方法,必须 保证当前运行的线程取得了该对象的控制权。 如果在没有控制权的线程里执行对象的以上三种方法, 就会报ng.IllegalMonitorStateException异常。 就会报ng.IllegalMonitorStateException异常。 JVM是基于多线程的,默认情况下不能保证运行时线程 JVM是基于多线程的,默认情况下不能保证运行时线程 的时序性。
Java中锁的概念 Java中锁的概念
多线程的线程同步机制实际上是靠锁的概念来控制的, 那么在Java程序当中,锁是如何体现的呢? 那么在Java程序当中,锁是如何体现的呢? 在Java程序运行时环境中,JVM需要对两类线程共享的 Java程序运行时环境中,JVM需要对两类线程共享的 数据进行协调:1 数据进行协调:1)保存在堆中的实例变量 ;2)保存在 方法区中的类变量 。这两类数据是被所有线程共享的。 在java虚拟机中,每个对象和类在逻辑上都是和一个监 java虚拟机中,每个对象和类在逻辑上都是和一个监 视器相关联的;对于对象来说,相关联的监视器保护对 象的实例变量;对于类来说,监视器保护类的类变量。 为了实现监视器的排他性监视能力,java虚拟机为每一 为了实现监视器的排他性监视能力,java虚拟机为每一 个对象和类都关联一个锁。代表任何时候只允许一个线 程拥有的特权。线程访问实例变量或者类变量不需锁, 但是如果线程获取了锁,那么在它释放这个锁之前,就 没有其他线程可以获取同样数据的锁了,锁住一个对象 就是获取对象相关联的监视器。
相关主题