线程同步

线程同步

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时,观察运行结果。
(存在问题,请自己实际操作,两条同时输出,结果有问题)
存在问题

存在问题

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值