首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > 编程 >

线程同步化的了解以及使用

2013-10-08 
线程同步化的理解以及使用又是忙碌的一天,Java结束了复习,老师也开始讲新的课程了。下午下课,很任性的没有

线程同步化的理解以及使用

        又是忙碌的一天,Java结束了复习,老师也开始讲新的课程了。下午下课,很任性的没有去吃饭,后来与老师讨论时就说到了线程同步的问题。有了点自己的感触,想给大家分享一下,希望能让像我一样的程序员能有所收获。

        我们都知道,多线程编程为程序开发带来了很多的便利,但是也带来了一些问题,这些问题时在程序开发过程中必须进行处理的。这些问题的核心是,如果多个线程同时访问一个资源,如变量、文件等,如何保证访问安全?

        举个例子,假设有两个线程:线程A和线程B,并且程序为这两个线程开辟了一个公共的内存空间,情况则是线程B写一次,线程A读一次。那么则会出现如下几种情况:

        1.在某个时候线程B运行速度比较快,在线程A未读取上一个数据之前,B就写了第二次数据,造成数据遗漏。

        2.在某个时候线程A运行速度比较快,它读完一次数据之后,线程B还没来得及写,线程A又来读第二次。结果线程A读不到数据,导致运行出错。        3.线程B正在写数据时,线程A也来读取数据,这时可能线程B还没将数据写完,线程A将数据读走,导致程序出错。 接下来,就让我用代码来演示同步产生的错误的情况:  利用线程来模拟售票系统:  票类: 
public class Tickets {public int total;//在票这个类中定义票的数量public Tickets(int total){//初始化this.total=total;}public  void action(String threadName){System.out.println(threadName+"卖票之前"+total);total--;System.out.println(threadName+"卖票之后"+total);}}

线程类:
public class TicketsThread extends Thread{private Tickets tickets;//票的对象public TicketsThread(Tickets tickets) {//初始化票的对象this.tickets=tickets;}@Overridepublic void run() {while(true){if(tickets.total<=1){break;}try {Thread.sleep(200);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}tickets.action(Thread.currentThread().getName());}}}

测试类:
public class Test {public static void main(String[] args) {Tickets t=new Tickets(10);TicketsThread tt1=new TicketsThread(t);tt1.start();TicketsThread tt2=new TicketsThread(t);tt2.start();}}
通过测试类的运行结果为:
线程同步化的了解以及使用        从结果来看,明显在我用荧光笔标识的地方有错误,明显这里应该是“Thread-0卖票之前3”,也就是读到了“脏数据”(就是不该读到的数据),再把测试类反复运行,总难免会有一些读错数据的情况,那么我们就不难发现线程在同步中也会产生一些无法预料的错误,那么究竟该怎么解决呢?       <注:在这里,我并没有说每次测试都是错误的,但是完全正确的几率十分低>       在多线程编程中,这种被多个线程同时访问的资源叫做临界资源,那么解决临界资源问题,最基本、最简单的思路就是使用同步关键字synchronized。       因为我们同时访问的所谓临界资源就是票这个类,所以只需要改正这里即可,以下是代码:
public class Tickets {public int total;//在票这个类中定义票的数量public Tickets(int total){//初始化this.total=total;}public synchronized void action(String threadName){//定义同步化,即线程A访问时,线程B必须等待;线程B访问时,线程A必须等待System.out.println(threadName+"卖票之前"+total);total--;System.out.println(threadName+"卖票之后"+total);}}

      再让我们来看看输出的结果:线程同步化的了解以及使用       那么,这个关键字的作用到底是什么呢?让我们再回到我一开始举的例子上,我们可以这样理解,当有此关键字存在时“定义同步化,即线程A访问时,线程B必须等待;线程B访问时,线程A必须等待”。       希望能给一些和我一样的初学者一些帮助,也希望技术大牛们多多指点。

热点排行