第3章 数据同步

前一章中,介绍了许多基础知识:如何创建、启动、终结、命名线程、监控生命周期,等等。然而,那一章的例子讲解的线程或多或少是独立的:在它们之间不需要共享数据。

但在有些例子中,我们需要让一个线程能够做出判断:其他线程是否完成了它们的任务(也就是那个done标记)。在其他例子中,我们需要改变被用在动画canvas中的字符变量;这是由一个不同于重画canvas的Swing线程的一个线程完成的。当时,我们掩饰了细节,这可能会给你一个暗示它们不重要。然而,我们必须要理解,就是当2个线程共享数据时,复杂度会增加。不管我们是正在实现一个大型共享数据库还是仅仅共享一个done标记,这些复杂性必须要考虑。

本章将讨论线程间共享数据的问题。线程间共享数据会变得麻烦,就是因为竞争条件会同时(也就是并发)地访问相同的数据。将学习什么是竞争条件,如何解决它呢?

3.1、Synchronized关键字

线程间没有竞争条件的原因是对象中没有数据被共享。然而,其他线程会调用该对象的方法。这种情况下,就会有一个竞争条件。调用newCharacter()方法的线程和调用paintComponent()方法的线程会访问相同的数据。随机字符生成线程可能会修改字符(但这个时候event-dispatching线程正在使用该字符)。这2个线程还会修改X location。

竞争条件存在的原因是paintComponent()和newCharacter()方法不是atomic的。稍后我们将详细介绍竞争条件,现在我们只需要理解竞争条件会产生不同的结果,包括依赖于执行顺序产生的不在预料中的结果。

扫描二维码关注公众号,回复: 827406 查看本文章

对Atomic的解释:atomic一词与原子有关,曾经被认为是物质的最小单元,不能再被拆分成独立的部分。当计算机代码被认为是atomic的时候,在它的执行过程中,它就不能被中断。这可以由硬件或软件模拟来实现。通常,硬件提供atomic指令,然后软件用它来实现atomic方法。

Java语言提供了synchronized关键字;和其他threading系统相比,该关键字可以让程序员访问一个资源(和mutex lock非常类似)。它对我们的作用,仅仅是阻止2个或更多个线程在同一时间调用同一对象上的方法。

Java中,每个对象都有一个与它相关联的锁。当一个方法被声明为synchronized,执行线程就必须获取该对象的锁才能继续做事。方法完成后,锁就自动释放了。不管方法是如何返回的,包括通过异常,锁都会被释放。

3.2、Volatile关键字

在这个例子中,实际上还有一个线程问题,并且是与setDone()方法有关。该方法是从event-dispatching线程中被调用的,就是当Stop按钮被按下时;它是被一个事件处理器调用的(就是一个actionPerformed()方法),该事件处理器是SwingTypeTester类的一个内部类。这里的问题就是该方法会改变正在被另一个线程用的数据:done标记,它被AnimatedDisplayCanvas类的线程在访问。

因此,我们不能仅仅同步这2个方法,就像我们之前那样?是的但也不是。是的,java的synchronized关键字可以解决该问题。但不是,目前我们学到的技术还不能正常工作。原因呢,和run()方法有关。如果我们对run()和setDone()方法都进行了同步,setDone()方法又如何在什么时候执行呢?run()方法不会退出,直到done标记被设置,但done标记不能被设置,因为setDone()方法只能直到run()方法完成后才能执行。

未完。。。。。。。。。。。。。。。。

猜你喜欢

转载自zsjg13.iteye.com/blog/2213659