第3章 数据同步

本文探讨了多线程环境中共享数据的复杂性,介绍了synchronized和volatile关键字的作用及使用方法,帮助开发者理解并解决竞争条件问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

 

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

 

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

 

3.1、Synchronized关键字

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

 

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

 

对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()方法完成后才能执行。

 

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

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值