自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(46)
  • 收藏
  • 关注

原创 如何理解顺序一致性?(2)

(在单独考虑进程1的程序时,这两个操作的执行顺序无关紧要。如果读取操作请求的是队列中已经有写请求的内存位置的内容,那么该读取操作不需要进入队列。为了减少等待,处理器可以向内存模块发出存储请求,而不指定要存储的值。当然,在内存模块接收到要存储的值之前,存储请求实际上不能被执行。通常,处理器在知道前面的存储请求将要存储的值之前,就已经准备好发出内存获取请求了(我们首先观察到,顺序处理器可以以任何顺序执行进程1的“b:= 1”(只有在值被计算之后才能存储值,这使得满足需求R1变得复杂。

2023-11-21 11:43:58 86

原创 如何理解顺序一致性?(1)

这一系列文章基于并发大师Lamport的“How to Make a Multiprocessor Computer That Correctly Executes Multiprocess Programs”这篇短文(“顺序一致性”的概念最早就来自于此文)。这篇文章虽然很短,但是信息量很大,因为其省略了一些细节的描述以及原理的阐述,而本系列文章在翻译这篇文章的基础上对这些关键细节和原理进行了补充,从而使得我们能够更加深入地理解这篇文章的深刻内涵和要义。

2023-10-21 15:35:25 143

原创 如何理解UML2.5.1(05篇)

标记subsets和redefines可以说是UML2.5.1中最重要的一对标记。标记subsets相对要好理解一些,但是redefines的含义就没有那么直白。先看一下目前已知的subsets和redefines的效果:假定图一中A1和B1的关联两端的标记都是subsets,那么这一对标记就意味着在向A1和B1的关联添加一个新链接时,也要将此链接添加到A和B之间的关联中;假定图一中A1和B1的关联两端的标记都是redefines,那么这一

2022-12-23 20:58:15 1050 1

原创 如何理解UML2.5.1(04篇)

通过这个例子,也给我们一个提示:如果某个类图有匪夷所思的内容,则可以结合相关的“Classifier Descriptions”和“Association Descriptions”中的内容进行复核,如果两者确实一致,则是我们的理解有问题;如果两者不一致,则是原文中的错误。

2022-12-23 15:44:59 964

原创 如何理解UML2.5.1(03篇)

下面先简单列举一下subsets和redefines的特点: 关联端点具有标识subsets表明subsets一端的对象集合是被subsets一端的对象集合的子集。此时,subsets一端的类与被subsets一端的类之间必须存在继承关系。同时,subsets一端的角色名一定与被subsets一端的角色名不同。 关联端点具有标识redefines表明这是对被redefines的关联端点的重定义。此时,有两种情况:如果关联一端由类拥有

2022-12-08 18:25:07 628

原创 如何理解UML2.5.1(02篇)

一个关联此端(Behavior)是不超过关联另一端重数上界(这里是1)的关联另一端(BehavioralFeature)对应的关联此端的角色名(method),(BehavioralFeature)称为关联此端(Behavior)的关联另一端的角色名(specification)。

2022-12-06 15:39:48 457

原创 如何理解UML2.5.1(01篇)

那么我们到底能够从UML上获取哪些对信息系统构建有帮助的内容呢?通过观察UML2.5.1,本人发现了一个可以借鉴UML2.5.1的地方,那就是其中花样繁多的类图,尤其是被称为“抽象语法”的类图以及大量的类图例子。因为这些类图都是对建模领域所需要解决的问题的高度抽象,如果我们也能够掌握这种抽象能力,那将会使我们对所要构建的信息系统的建模工作大有裨益。而本文章系列的重点就在于通过对一些UML类图实例的理解来帮助那些对UML2.5.1中类图感到一筹莫展的读者进行学习和理解。

2022-11-30 11:22:44 638

原创 Action模型 -- 增强型UML建模和后台代码的自动生成工具

Action模型主要是融合了三项堪称黑科技的技术:无需考虑并发的并发模型、无需时间输入的时间模型、N元关联也支持Qualifier的关联模型。只要是有增删改查需求的系统都可以应用Action模型,从而使得Action模型具有广阔的应用前景。

2022-11-17 19:58:22 564

翻译 C#3.0核心技术-第19章线程-全新翻译注释-19.14(2)

19.14.2 单线程定时器.NET框架提供了被设计用来为Windows Form和WPF应用程序消除线程安全问题的定时器:l System.Windows.Forms.Timer(Windows Form)l System.Windows.Threading.DispatcherTimer(WPF)原文注:单线程计数器不是设计用来工作在它们相应环境之外的。比方说,如果你在一个

2010-05-23 20:39:00 449

翻译 C#3.0核心技术-第19章线程-全新翻译注释-19.14(1)

19.14 定时器(Timer)如果你需要以规则的间隔重复地运行一些方法,最容易的方法是使用定时器。定时器是方便的,与下列技术相比较,定时器使用内存和资源是有效率的:这个不但永久地占用一个线程的资源,而且如果没有额外的代码,DoSomeAction将在每天的迟一点的时间发生(译者注:因为DoSomeAction的运行也要占用时间,特别是如果运行时间比较长的情况下,所以每天都向后推迟一点

2010-05-23 20:38:00 559

翻译 C#3.0核心技术-第19章线程-全新翻译注释-19.13(3)

19.13.1.1 锁递归一般而言,嵌套或者递归锁定是ReaderWriterLockSlim所禁止的。因此,下列代码抛出一个异常:然而,如果你像下面一样构造ReaderWriterLockSlim,则不会有运行错误:这确保仅当你计划这样做时递归锁定才会发生。递归锁定能够带来不希望的复杂性,因为获得超过一种锁是可能的:基本规则是一旦你已经获得了一个锁,随后的递归锁可以更

2010-05-23 20:36:00 511

翻译 C#3.0核心技术-第19章线程-全新翻译注释-19.13(2)

19.13.1 可升级的锁与递归有些时候,在一个单一的原子操作中以一个读锁交换一个写锁很有用。例如,假定你想要加入一个条目到list中,仅当这个条目没有已经在list中。理想地,你希望最小化花费在持有(互斥的)写锁上的时间,所以你可以像下面一样处理:1. 获得一个读锁。2. 测试是否条目已经在list中,如果是这样,释放锁并返回。3. 释放读锁。4. 获得一个写锁。5. 加

2010-05-23 20:35:00 463

翻译 C#3.0核心技术-第19章线程-全新翻译注释-19.13(1)

19.13 ReaderWriterLockSlim经常,一个类型的实例对于并发读操作时线程安全的,但是对于并发更新不是(对于并发读和更新也不是)。对于像一个文件那样的资源这也是真的。尽管对所有访问模式(译者注:即读、更新、读和更新)使用一个简单的互斥锁来保护这种类型的实例通常可以获得成功,但是它不合理地限制了并发,如果这里有很多读(译者注:操作的执行)者却仅有偶尔的更新。这能够发生的一个例子

2010-05-23 20:34:00 511

翻译 C#3.0核心技术-第19章线程-全新翻译注释-19.12(2)

19.12.1 子类化BackgroundWorkerBackgroundWorker不是密封的,并且提供了一个虚的OnDoWork方法,暗示了使用它的另一种模式。在写一个潜在的长时间运行的方法中,你可以写一个返回子类化BackgroundWorker的额外版本,预先配置好以并发地执行这个工作。消费者(译者注:即调用者)然后只需要处理RunWorkerCompleted和ProgressCha

2010-05-23 20:31:00 394

翻译 C#3.0核心技术-第19章线程-全新翻译注释-19.12(1)

19.12 BackgroundWorkerBackgroundWorker是一个在System.ComponentModel命名空间中的帮助类,用于管理一个工作线程。它提供了下列特征:l 一个cancel标志用于向一个工作线程发信号以结束(译者注:工作线程)而不使用Abortl 一个用于报告进度、完成以及撤销的标准协议l 一个IComponent的实现以允许它被放入Visual

2010-05-23 20:30:00 417

翻译 C#3.0核心技术-第19章线程-全新翻译注释-19.11

19.11 局部存储(Local Storage)这一章的大部分关注于同步构造以及使得线程们并发访问相同数据而引起的话题。然而,有些时候,你希望保持数据孤立,确保每一个线程有一个单独的拷贝。局部变量恰好可以做到这一点,但是它们仅对瞬态数据有效。Thread类提供GetData和SetData方法在“槽”中存储非瞬态孤立数据,这些数据的值在方法调用之间保持。你可能会为想到这样的需求而焦头烂额

2010-05-23 20:28:00 480

翻译 C#3.0核心技术-第19章线程-全新翻译注释-19.10(3)

19.10.3 安全的撤销中止另外一个线程的替代方法是实现一个模式,工作线程据此周期性地检查一个cancel标志,如果标志为true则退出。为了中止,鼓动者(译者注:即发出中止命令的那个线程)简单地设置标志,然后等待工作线程照着做:代码视图:(译者注:相较由其它线程在任意时刻调用被中止线程的Abort方法,由被中止的线程自己调用自己的Abort方法是相关finally块能够被执行的

2010-05-23 20:25:00 579

翻译 C#3.0核心技术-第19章线程-全新翻译注释-19.10(2)

19.10.2 中止一个被阻塞的线程还能够借助于它的Abort方法被强制性地释放。这里有一个与调用Interrupt近似的效果,除了一个代替ThreadInterruptedException的ThreadAbortException异常被抛出。更进一步,这个异常将会在catch块的最后被重新抛出(在一次一劳永逸地终止线程的尝试中)(译者注:即通过不断地重新抛出ThreadAbortExcep

2010-05-23 20:24:00 404

翻译 C#3.0核心技术-第19章线程-全新翻译注释-19.10(1)

19.10 中断和中止(Interrupt and Abort)如果解除阻塞的条件永远不会满足并且没有超时被指定,则所有的阻塞方法—Sleep、Join、EndInvoke、WaitOne、以及Wait—会永远阻塞下去。有时候,过早地释放一个阻塞的线程是有用处的;例如,当结束一个应用程序时。两个方法可以完成这个:Thread.InterruptThread.AbortAbort方法

2010-05-23 20:23:00 452

翻译 C#3.0核心技术-第19章线程-全新翻译注释-19.9(6)

19.9.5 仿真等待句柄你也许已经注意到在前面的例子中有这样一个模式:两个等待循环都有下列结构:flag在另一个线程中设置为true。这实际上是模仿一个AutoResetEvent。如果我们忽略flag=false,我们得到了一个ManualResetEvent;如果我们用一个整数字段替换标志,我们得到一个Semaphore。在大多数情况下,仿真跨越一系列等待句柄工作的静态方法是

2010-05-23 20:21:00 510

翻译 C#3.0核心技术-第19章线程-全新翻译注释-19.9(5)

19.9.4 双路信令比方说我们想要连续发信号通知一个线程五次:代码视图:这个程序是有缺陷的:在工作线程没有保持锁的任何时候,甚至可能在工作线程开始之前,主线程中的for循环能够自由地贯穿整个它的五次迭代!生产者/消费者的例子不会遭遇到这个问题,因为如果主线程走到工作线程的前面,每个请求会被放入队列。而在这个例子中,如果工作线程仍旧忙于前一个任务,我们需要主线程在每个迭代处阻塞。

2010-05-23 20:20:00 386

翻译 C#3.0核心技术-第19章线程-全新翻译注释-19.9(4)

19.9.3 等待超时当调用Wait时,你可以指定一个超时,要么以毫秒(译者注:为单位)要么以一个TimeSpan(译者注:表示)。如果Wait方法因为一个超时而放弃,则它返回false。超时仅仅应用在等待阶段。因此,一个包含超时的Wait做下列事情:1. 释放底层的锁2. 阻塞直到被施以脉冲,或者超时流逝过去3. 重新获得底层的锁指定一个超时就像请求CLR在超时时间间隔之后给

2010-05-23 20:19:00 452

翻译 C#3.0核心技术-第19章线程-全新翻译注释-19.9(3)

19.9.2 生产者/消费者队列一个生产者/消费者队列在线程处理中是普遍需要的。这里是它是如何工作的:l 一个队列被建立以描述任务。l 当一个任务需要执行,它被放入队列,允许调用者继续干其它事情。l 一个或者更多的工作线程在后台拼命地工作,摘取和执行队列中的任务。(译者注:将任务放入队列是生产者的行为;将任务从队列中摘取并执行是消费者的行为。)这个模型的好处是你可以精确地控

2010-05-23 20:18:00 372

翻译 C#3.0核心技术-第19章线程-全新翻译注释-19.9(2)

19.9.1 如何使用Wait和Pulse这里是你如何使用Wait和Pulse:1. 定义一个单一的字段用作同步对象,例如:2. 定义字段(一个或多个),用在你的定制的阻塞条件(一个或者多个)中,例如:3. 无论任何时候你想阻塞,包含下列代码:4. 无论任何时候你改变(或者潜在地改变)一个阻塞条件,包含这个代码:(如果你想改变一个阻塞条件并且想要阻塞,你可以

2010-05-23 20:16:00 413

翻译 C#3.0核心技术-第19章线程-全新翻译注释-19.9(1)

19.9 使用Wait和Pulse的信令Monitor类提供另一种信令构造,借助于两个静态方法:Wait和Pulse。原则是你使用定制的标志或者字段(包含在lock语句中)写你自己的信令逻辑,然后导入Wait和Pulse命令减轻CPU的spinning。这个低层次方法的好处就是仅使用Wait、Pulse、和lock语句,你就能够获得AutoResetEvent、ManualResetEvent

2010-05-23 20:15:00 399

翻译 C#3.0核心技术-第19章线程-全新翻译注释-19.8(4)

19.8.5 WaitAny、WaitAll、和SignalAndWait除了Set、WaitOne、和Reset方法外,WaitHandle类上有静待方法以解决更复杂的同步问题。WaitAny、WaitAll、以及SignalAndWait方法跨越多个句柄等待。等待句柄可以是不同的类型,它们(译者注:指等待句柄)包括Mutex和Semphore对象,因为这些也由抽象的WaitHandle类派

2010-05-23 20:12:00 466

翻译 C#3.0核心技术-第19章线程-全新翻译注释-19.8(3)

19.8.3 创建一个跨进程EventWaitHandleEventWaitHandle的构造方法允许一个“命名的”EventWaitHandler被创建,(译者注:此EventWaitHandler)有能力跨越多个进程进行操作。名字就是一个简单的字符串,并且它能够不是无意间与其它(译者注:EventWaitHandler)的名字冲突的任何字串!如果名字在计算机上已经被使用,你得到一个到相同E

2010-05-23 20:10:00 340

翻译 C#3.0核心技术-第19章线程-全新翻译注释-19.8(2)

19.8.1 创建和处置等待句柄事件等待句柄能够以两种方式中的一种被创建。第一种是借助它们的构造方法:如果boolean参数是true,句柄的Set方法在构造之后立即被自动地调用。实例化的另外一种方法是借助于基类,EventWaitHandle:一旦你已经使用完了一个等待句柄,你能够调用它的Close方法以释放操作系统资源。或者,你能够简单地丢弃所有到等待句柄的引用以允许垃圾回

2010-05-23 20:09:00 323

翻译 C#3.0核心技术-第19章线程-全新翻译注释-19.8(1)

19.8 使用事件等待句柄的信令(signaling)事件等待句柄被用于信令。信令是一个线程等待直到从另一个线程接收到消息。事件等待句柄是信令构造中最简单的,并且它们与C#事件(Event)无关。它们以两种形式出现:AutoResetEvent和ManualResetEvent。两者都是基于共同的EventWaitHandle类(译者注:即以EventWaitHandle类为基类),从这里(译

2010-05-23 20:08:00 373

翻译 C#3.0核心技术-第19章线程-全新翻译注释-19.7(2)

19.7.2 内存屏障(Memory Barriers)和易变性(Volatility)考虑这个类:有没有可能Wait方法可以写出“False”?答案是肯定的,在一个多核或者多处理器的机器上。Repented和endIsNigh字段能够被缓存在CPU的寄存器中以提升性能,这意味着在它们的更新值被写回到内存时之前有一个延迟(译者注:正是因为这个延迟导致了Console.Write(r

2010-05-23 19:57:00 327

翻译 C#3.0核心技术-第19章线程-全新翻译注释-19.7(1)

19.7 非阻塞同步在前面,我们说过甚至在赋值或递增一个字段的简单情况下都会引起同步的需求。尽管锁定总是可以满足这个需求,但是一个竞争的锁意味着一个线程必须阻塞,遭受被暂时地反调度(译者注:指线程从运行状态调度到非运行状态)的开销和潜伏期(译者注:潜伏期指一个操作从发出命令到命令产生效果的这段时间)。.NET框架的非阻塞同步构造能够执行简单的操作而无需阻塞、暂停、或者等待。这包括使用具有严格原

2010-05-23 19:56:00 318

翻译 C#3.0核心技术-第19章线程-全新翻译注释-19.6(3)

19.6.3 在富客户应用程序中的线程安全Windows Forms和Windows Presentation Foundation(WPF)库都有特别的线程模型。尽管每一个有一个单独的实现,但它们在如何实现它们的功能方面很相似。组成一个富客户的对象在Windows Forms的情况下主要基于Control类(译者注:即以Control类为基类),在WPF的情况下主要基于Dependenc

2010-05-23 19:54:00 489

翻译 C#3.0核心技术-第19章线程-全新翻译注释-19.6(2)

19.6.2 在应用服务器中的线程安全应用服务器需要多线程以处理同时发生的客户请求。WCF、ASP.NET、和Web服务应用程序是隐含的多线程;这同样也适用于使用一个诸如TCP或者HTTP的网络通道的Remoting服务器应用程序。这意味着当在服务器端书写代码时,如果这里在处理客户请求的线程中有任何交互的可能,你必须考虑线程安全。幸运的是,这个可能性很小;一个典型的服务器类要么是无状态(没有字

2010-05-23 19:53:00 331

翻译 C#3.0核心技术-第19章线程-全新翻译注释-19.6(1)

19.6 线程安全一个程序或者方法是线程安全的如果它在面对任何多线程场景中都没有不确定性。线程安全性主要通过锁定和减少线程交互的可能性来达到。通用类型在它们的整体中很少是线程安全的(译者注:即一个通用类型做到部分线程安全并不困难,难的是整个类型都是线程安全的),由于下列原因:l 全线程安全的开发负担可以是相当巨大的,特别的,如果一个类型有很多字段(在任意的多线程上下文中每个字段都是一个

2010-05-23 19:52:00 447

翻译 C#3.0核心技术-第19章线程-全新翻译注释-19.5(2)

19.5.4 锁定和原子性如果一组变量总是被在同一个锁中读和写,你可以说这些变量被原子性地读和写。让我们假定字段x和y总是在对象locker上的锁中被读和赋值:人们可以说x和y被原子性地访问,因为代码块不能够以这样一种方式(改变x或者y并使它的结果无效)被另一个线程的活动分割或者占先。你将永远不会得到一个除零错误,如果x和y一直在这个同样的互斥锁内被访问。指令原子性是一个尽管相近但

2010-05-23 19:47:00 421

翻译 C#3.0核心技术-第19章线程-全新翻译注释-19.5(1)

19.5 锁定互斥锁被用来确保同一时间仅有一个线程能够进入特定的代码段。.NET框架提供两个互斥锁构造:lock和Mutex。在这两个方法中,lock构造更快和更方便。然而Mutex有一个特殊的地方,它的锁可以跨越计算机中不同进程中的应用程序。这一节关注lock构造;后面我们显示Mutex如何被用来进行跨越进程的锁定。最后,我们介绍Semaphore,.NET的非互斥锁构造。让我们以下

2010-05-23 19:46:00 509

翻译 C#3.0核心技术-第19章线程-全新翻译注释-19.4

19.4 同步到目前为止,我们已经描述了如何在一个线程上开始一个任务,如何配置一个线程,如何双向的传递数据。我们也描述了局部变量如何为一个线程所私有以及引用如何能够在线程之间被共享以允许它们(译者注:指线程)借助公共字段通信。下一步是同步:为了一个可预测的结果协调线程的行为。当线程访问相同的数据时同步特别重要;在这个领域搁浅是惊人地容易(译者注:这句话的意思是在线程同步的编程中非常容易出错

2010-05-23 19:40:00 517

翻译 C#3.0核心技术-第19章线程-全新翻译注释-19.3

19.3 异步委托在前面一节,我们描述了如何传递数据给线程,使用ParameterizedThreadStart和ThreadPool.QueueWorkerItem(译者注:这里应该是ThreadPool.QueueUserWorkItem)。有些时候你需要在另外一个方向上从一个线程得到返回值,当线程结束执行时。异步委托为这个提供了一个方便的机制,允许任意数量的有类型的参数在两个方向上传递。

2010-05-23 19:38:00 370

翻译 C#3.0核心技术-第19章线程-全新翻译注释-19.2(7)

19.2.6 异常处理任何在线程被创建时的作用域中的try/catch/finally块,当线程开始执行时,和它没有任何关系。考虑下列程序:try/catch语句在这个例子中是没有用的,新创建的线程将被一个未处理的NullReferenceException所拖累。当你认为每一个线程有一个独立的执行路径时这种行为是有意义的。补救措施是将异常处理移到Go方法的内部:你在生产应

2010-05-23 19:37:00 358

翻译 C#3.0核心技术-第19章线程-全新翻译注释-19.2(6)

19.2.5 线程优先权一个线程的优先权属性决定了它较同一进程中其它活动线程能够获得多少执行时间,以如下尺度:只有当多个线程同时活动时这才变得相关。提升线程的优先权不能够使它有能力执行实时工作,因为这仍旧受到应用程序的进程优先级的限制。为了执行实时工作,你必须也使用System.Diagnostics中的Process类提升进程的优先权(我们不告诉你如何做到这一点):Pro

2010-05-23 19:35:00 277

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除