线程同步

来源:互联网 发布:上海公积金算法 编辑:程序博客网 时间:2024/06/14 22:19

线程同步

Java程序中可以存在多个线程,但是在处理多线程问题时,必须注意这样一个问题:当两个或多个线程同时访问同一个变量,并且一些线程需要修改这个变量。程序应对这样的问题做出处理,否则可能发生混乱,比如一个工资管理负责人正在修改雇员的工资表,而一些雇员也正在领取工资,如果允许这样做必然初夏 混乱。因此,工资管理负责人正在修改工资表(包括他喝杯茶休息一会),将不允许任何雇员领取工资,也就是说这些雇员必须等待。

所谓线程同步就是若干个线程都需要使用一个synchronized(同步)修饰的方法,即程序中的若干个线程都需要使用一个方法,而这个方法用synchronized给予了修饰,多个线程调用synchronized方法必须遵守同步机制。

线程同步机制:当一个线程A使用synchronized方法时,其他线程想使用这个synchronized方法时就必须等待,直到线程A使用完该synchronized方法。

在使用多线程解决许多实际问题时,可能要吧某些修改数据的方法用方法用关键字synchronized来修饰,即使用同步机制。

下面的例子中有两个线程:会计和出纳,他俩共同拥有一个账本,他俩都可以使用saveOrTake(int amount)方法对账本进行访问,会计使用saveOrTake(int amount)方法时,向账本上写入存钱记录;出纳使用saveOrTake(int amount)方法时,向账本写入取钱记录。因此,当会计正在使用saveOrTake(int amount)时,出纳被禁止使用,反之也是这样。比如,会计使用saveOrTake(int amount)时,在账本上存入300万元,但在存入这笔钱时,每存入100万,就喝口茶,那么会计喝茶休息时,存钱这件事还没结束,即会计还没有使用saveOrTake(int amount)方法,出纳仍不能使用saveOrTake(int amount);出纳使用saveOrTake(int amount)时,在账本上取出150万元,但在取出这笔钱时,每取出50万元,就喝口茶,那么出纳喝茶休息时,会计不能使用saveOrTake(int amount),也就是说,程序要保证其中一人使用saveOrTake(int amount)时,另一个人将必须等待,即saveOrTake(int amount)方法应当是一个synchronized方法。

例子:
Example12_7.java

package com.liu;public class Example12_7 {    public static void main(String[] args) {        Bank bank=new Bank();        bank.setMoney(200);        Thread accountant,cashier;        accountant=new Thread(bank);        cashier=new Thread(bank);        accountant.setName("会计");        cashier.setName("出纳");        accountant.start();        cashier.start();    }}

Bank.java

package com.liu;public class Bank implements Runnable{    int money=200;    public void setMoney(int n){        money=n;    }    public void run(){        if(Thread.currentThread().getName().equals("会计"))            saveOrTake(300);        else if(Thread.currentThread().getName().equals("出纳"))            saveOrTake(150);    }    public synchronized void saveOrTake(int amount){//注意这里是同步即有synchronized        if(Thread.currentThread().getName().equals("会计")){            for(int i=1;i<=3;i++){                money=money+amount/3;                System.out.println(Thread.currentThread().getName()+"存入"+amount/3+",账上有"+money+"万,休息一会再存");                try{Thread.sleep(1000);                }catch(InterruptedException e){}            }        }else if(Thread.currentThread().getName().equals("出纳")){            for(int i=1;i<=3;i++){                money=money-amount/3;                System.out.println(Thread.currentThread().getName()+"取出"+amount/3+",账上有"+money+"万,休息一会在取");                try{                    Thread.sleep(1000);                }catch(InterruptedException e){}            }        }    }}

其运行结果:(一条一条输出到控制台,可以自己尝试运行查看效果)
正确的结果
当Bank.java 去掉saveOrTake方法的同步修饰synchronized时,观察运行结果。
(存在问题,请自己实际操作,两条同时输出,结果有问题)
存在问题

存在问题

原创粉丝点击